PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/metro-file-map/src/lib
Просмотр файла: TreeFS.js
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _constants = _interopRequireDefault(require("../constants"));
var _RootPathUtils = require("./RootPathUtils");
var _invariant = _interopRequireDefault(require("invariant"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
function isDirectory(node) {
return node instanceof Map;
}
function isRegularFile(node) {
return node[_constants.default.SYMLINK] === 0;
}
class TreeFS {
#cachedNormalSymlinkTargets = new WeakMap();
#rootDir;
#rootNode = new Map();
#pathUtils;
#processFile;
constructor({ rootDir, files, processFile }) {
this.#rootDir = rootDir;
this.#pathUtils = new _RootPathUtils.RootPathUtils(rootDir);
this.#processFile = processFile;
if (files != null) {
this.bulkAddOrModify(files);
}
}
getSerializableSnapshot() {
return this._cloneTree(this.#rootNode);
}
static fromDeserializedSnapshot({ rootDir, fileSystemData, processFile }) {
const tfs = new TreeFS({
rootDir,
processFile,
});
tfs.#rootNode = fileSystemData;
return tfs;
}
getModuleName(mixedPath) {
const fileMetadata = this._getFileData(mixedPath);
return (fileMetadata && fileMetadata[_constants.default.ID]) ?? null;
}
getSize(mixedPath) {
const fileMetadata = this._getFileData(mixedPath);
return (fileMetadata && fileMetadata[_constants.default.SIZE]) ?? null;
}
getDependencies(mixedPath) {
const fileMetadata = this._getFileData(mixedPath);
if (fileMetadata) {
return fileMetadata[_constants.default.DEPENDENCIES]
? fileMetadata[_constants.default.DEPENDENCIES].split(
_constants.default.DEPENDENCY_DELIM,
)
: [];
} else {
return null;
}
}
getDifference(files) {
const changedFiles = new Map(files);
const removedFiles = new Set();
for (const { canonicalPath, metadata } of this.metadataIterator({
includeSymlinks: true,
includeNodeModules: true,
})) {
const newMetadata = files.get(canonicalPath);
if (newMetadata) {
if (isRegularFile(newMetadata) !== isRegularFile(metadata)) {
continue;
}
if (
newMetadata[_constants.default.MTIME] != null &&
newMetadata[_constants.default.MTIME] != 0 &&
newMetadata[_constants.default.MTIME] ===
metadata[_constants.default.MTIME]
) {
changedFiles.delete(canonicalPath);
} else if (
newMetadata[_constants.default.SHA1] != null &&
newMetadata[_constants.default.SHA1] ===
metadata[_constants.default.SHA1] &&
metadata[_constants.default.VISITED] === 1
) {
const updatedMetadata = [...metadata];
updatedMetadata[_constants.default.MTIME] =
newMetadata[_constants.default.MTIME];
changedFiles.set(canonicalPath, updatedMetadata);
}
} else {
removedFiles.add(canonicalPath);
}
}
return {
changedFiles,
removedFiles,
};
}
getSha1(mixedPath) {
const fileMetadata = this._getFileData(mixedPath);
return (fileMetadata && fileMetadata[_constants.default.SHA1]) ?? null;
}
async getOrComputeSha1(mixedPath) {
const normalPath = this._normalizePath(mixedPath);
const result = this._lookupByNormalPath(normalPath, {
followLeaf: true,
});
if (!result.exists || isDirectory(result.node)) {
return null;
}
const { canonicalPath, node: fileMetadata } = result;
const existing = fileMetadata[_constants.default.SHA1];
if (existing != null && existing.length > 0) {
return {
sha1: existing,
};
}
const absolutePath = this.#pathUtils.normalToAbsolute(canonicalPath);
const maybeContent = await this.#processFile(absolutePath, fileMetadata, {
computeSha1: true,
});
const sha1 = fileMetadata[_constants.default.SHA1];
(0, _invariant.default)(
sha1 != null && sha1.length > 0,
"File processing didn't populate a SHA-1 hash for %s",
absolutePath,
);
return maybeContent
? {
sha1,
content: maybeContent,
}
: {
sha1,
};
}
exists(mixedPath) {
const result = this._getFileData(mixedPath);
return result != null;
}
lookup(mixedPath) {
const normalPath = this._normalizePath(mixedPath);
const links = new Set();
const result = this._lookupByNormalPath(normalPath, {
collectLinkPaths: links,
followLeaf: true,
});
if (!result.exists) {
const { canonicalMissingPath } = result;
return {
exists: false,
links,
missing: this.#pathUtils.normalToAbsolute(canonicalMissingPath),
};
}
const { canonicalPath, node } = result;
const type = isDirectory(node) ? "d" : isRegularFile(node) ? "f" : "l";
(0, _invariant.default)(
type !== "l",
"lookup follows symlinks, so should never return one (%s -> %s)",
mixedPath,
canonicalPath,
);
return {
exists: true,
links,
realPath: this.#pathUtils.normalToAbsolute(canonicalPath),
type,
};
}
getAllFiles() {
return Array.from(
this.metadataIterator({
includeSymlinks: false,
includeNodeModules: true,
}),
({ canonicalPath }) => this.#pathUtils.normalToAbsolute(canonicalPath),
);
}
linkStats(mixedPath) {
const fileMetadata = this._getFileData(mixedPath, {
followLeaf: false,
});
if (fileMetadata == null) {
return null;
}
const fileType = isRegularFile(fileMetadata) ? "f" : "l";
return {
fileType,
modifiedTime: fileMetadata[_constants.default.MTIME],
size: fileMetadata[_constants.default.SIZE],
};
}
*matchFiles({
filter = null,
filterCompareAbsolute = false,
filterComparePosix = false,
follow = false,
recursive = true,
rootDir = null,
}) {
const normalRoot = rootDir == null ? "" : this._normalizePath(rootDir);
const contextRootResult = this._lookupByNormalPath(normalRoot);
if (!contextRootResult.exists) {
return;
}
const {
ancestorOfRootIdx,
canonicalPath: rootRealPath,
node: contextRoot,
parentNode: contextRootParent,
} = contextRootResult;
if (!isDirectory(contextRoot)) {
return;
}
const contextRootAbsolutePath =
rootRealPath === ""
? this.#rootDir
: _path.default.join(this.#rootDir, rootRealPath);
const prefix = filterComparePosix ? "./" : "." + _path.default.sep;
const contextRootAbsolutePathForComparison =
filterComparePosix && _path.default.sep !== "/"
? contextRootAbsolutePath.replaceAll(_path.default.sep, "/")
: contextRootAbsolutePath;
for (const relativePathForComparison of this._pathIterator(
contextRoot,
contextRootParent,
ancestorOfRootIdx,
{
alwaysYieldPosix: filterComparePosix,
canonicalPathOfRoot: rootRealPath,
follow,
recursive,
subtreeOnly: rootDir != null,
},
)) {
if (
filter == null ||
filter.test(
filterCompareAbsolute === true
? _path.default.join(
contextRootAbsolutePathForComparison,
relativePathForComparison,
)
: prefix + relativePathForComparison,
)
) {
const relativePath =
filterComparePosix === true && _path.default.sep !== "/"
? relativePathForComparison.replaceAll("/", _path.default.sep)
: relativePathForComparison;
yield _path.default.join(contextRootAbsolutePath, relativePath);
}
}
}
addOrModify(mixedPath, metadata) {
const normalPath = this._normalizePath(mixedPath);
const parentDirNode = this._lookupByNormalPath(
_path.default.dirname(normalPath),
{
makeDirectories: true,
},
);
if (!parentDirNode.exists) {
throw new Error(
`TreeFS: Failed to make parent directory entry for ${mixedPath}`,
);
}
const canonicalPath = this._normalizePath(
parentDirNode.canonicalPath +
_path.default.sep +
_path.default.basename(normalPath),
);
this.bulkAddOrModify(new Map([[canonicalPath, metadata]]));
}
bulkAddOrModify(addedOrModifiedFiles) {
let lastDir;
let directoryNode;
for (const [normalPath, metadata] of addedOrModifiedFiles) {
const lastSepIdx = normalPath.lastIndexOf(_path.default.sep);
const dirname = lastSepIdx === -1 ? "" : normalPath.slice(0, lastSepIdx);
const basename =
lastSepIdx === -1 ? normalPath : normalPath.slice(lastSepIdx + 1);
if (directoryNode == null || dirname !== lastDir) {
const lookup = this._lookupByNormalPath(dirname, {
followLeaf: false,
makeDirectories: true,
});
if (!lookup.exists) {
throw new Error(
`TreeFS: Unexpected error adding ${normalPath}.\nMissing: ` +
lookup.canonicalMissingPath,
);
}
if (!isDirectory(lookup.node)) {
throw new Error(
`TreeFS: Could not add directory ${dirname}, adding ${normalPath}. ` +
`${dirname} already exists in the file map as a file.`,
);
}
lastDir = dirname;
directoryNode = lookup.node;
}
directoryNode.set(basename, metadata);
}
}
remove(mixedPath) {
const normalPath = this._normalizePath(mixedPath);
const result = this._lookupByNormalPath(normalPath, {
followLeaf: false,
});
if (!result.exists) {
return null;
}
const { parentNode, canonicalPath, node } = result;
if (isDirectory(node) && node.size > 0) {
throw new Error(
`TreeFS: remove called on a non-empty directory: ${mixedPath}`,
);
}
if (parentNode != null) {
parentNode.delete(_path.default.basename(canonicalPath));
if (parentNode.size === 0 && parentNode !== this.#rootNode) {
this.remove(_path.default.dirname(canonicalPath));
}
}
return isDirectory(node) ? null : node;
}
_lookupByNormalPath(
requestedNormalPath,
opts = {
followLeaf: true,
makeDirectories: false,
},
) {
let targetNormalPath = requestedNormalPath;
let seen;
let fromIdx = opts.start?.pathIdx ?? 0;
let parentNode = opts.start?.node ?? this.#rootNode;
let ancestorOfRootIdx = opts.start?.ancestorOfRootIdx ?? 0;
const collectAncestors = opts.collectAncestors;
let unseenPathFromIdx = 0;
while (targetNormalPath.length > fromIdx) {
const nextSepIdx = targetNormalPath.indexOf(_path.default.sep, fromIdx);
const isLastSegment = nextSepIdx === -1;
const segmentName = isLastSegment
? targetNormalPath.slice(fromIdx)
: targetNormalPath.slice(fromIdx, nextSepIdx);
const isUnseen = fromIdx >= unseenPathFromIdx;
fromIdx = !isLastSegment ? nextSepIdx + 1 : targetNormalPath.length;
if (segmentName === ".") {
continue;
}
let segmentNode = parentNode.get(segmentName);
if (segmentName === ".." && ancestorOfRootIdx != null) {
ancestorOfRootIdx++;
} else if (segmentNode != null) {
ancestorOfRootIdx = null;
}
if (segmentNode == null) {
if (opts.makeDirectories !== true && segmentName !== "..") {
return {
canonicalMissingPath: isLastSegment
? targetNormalPath
: targetNormalPath.slice(0, fromIdx - 1),
exists: false,
missingSegmentName: segmentName,
};
}
segmentNode = new Map();
if (opts.makeDirectories === true) {
parentNode.set(segmentName, segmentNode);
}
}
if (
(nextSepIdx === targetNormalPath.length - 1 &&
isDirectory(segmentNode)) ||
(isLastSegment &&
(isDirectory(segmentNode) ||
isRegularFile(segmentNode) ||
opts.followLeaf === false))
) {
return {
ancestorOfRootIdx,
canonicalPath: isLastSegment
? targetNormalPath
: targetNormalPath.slice(0, -1),
exists: true,
node: segmentNode,
parentNode,
};
}
if (isDirectory(segmentNode)) {
parentNode = segmentNode;
if (collectAncestors && isUnseen) {
const currentPath = isLastSegment
? targetNormalPath
: targetNormalPath.slice(0, fromIdx - 1);
collectAncestors.push({
ancestorOfRootIdx,
node: segmentNode,
normalPath: currentPath,
segmentName,
});
}
} else {
const currentPath = isLastSegment
? targetNormalPath
: targetNormalPath.slice(0, fromIdx - 1);
if (isRegularFile(segmentNode)) {
return {
canonicalMissingPath: currentPath,
exists: false,
missingSegmentName: segmentName,
};
}
const normalSymlinkTarget = this._resolveSymlinkTargetToNormalPath(
segmentNode,
currentPath,
);
if (opts.collectLinkPaths) {
opts.collectLinkPaths.add(
this.#pathUtils.normalToAbsolute(currentPath),
);
}
const remainingTargetPath = isLastSegment
? ""
: targetNormalPath.slice(fromIdx);
const joinedResult = this.#pathUtils.joinNormalToRelative(
normalSymlinkTarget.normalPath,
remainingTargetPath,
);
targetNormalPath = joinedResult.normalPath;
if (
collectAncestors &&
!isLastSegment &&
(normalSymlinkTarget.ancestorOfRootIdx === 0 ||
joinedResult.collapsedSegments > 0)
) {
let node = this.#rootNode;
let collapsedPath = "";
const reverseAncestors = [];
for (
let i = 0;
i <= joinedResult.collapsedSegments && isDirectory(node);
i++
) {
if (
i > 0 ||
normalSymlinkTarget.ancestorOfRootIdx === 0 ||
joinedResult.collapsedSegments > 0
) {
reverseAncestors.push({
ancestorOfRootIdx: i,
node,
normalPath: collapsedPath,
segmentName: this.#pathUtils.getBasenameOfNthAncestor(i),
});
}
node = node.get("..") ?? new Map();
collapsedPath =
collapsedPath === ""
? ".."
: collapsedPath + _path.default.sep + "..";
}
collectAncestors.push(...reverseAncestors.reverse());
}
unseenPathFromIdx = normalSymlinkTarget.startOfBasenameIdx;
if (seen == null) {
seen = new Set([requestedNormalPath]);
}
if (seen.has(targetNormalPath)) {
return {
canonicalMissingPath: targetNormalPath,
exists: false,
missingSegmentName: segmentName,
};
}
seen.add(targetNormalPath);
fromIdx = 0;
parentNode = this.#rootNode;
ancestorOfRootIdx = 0;
}
}
(0, _invariant.default)(
parentNode === this.#rootNode,
"Unexpectedly escaped traversal",
);
return {
ancestorOfRootIdx: 0,
canonicalPath: targetNormalPath,
exists: true,
node: this.#rootNode,
parentNode: null,
};
}
hierarchicalLookup(mixedStartPath, subpath, opts) {
const ancestorsOfInput = [];
const normalPath = this._normalizePath(mixedStartPath);
const invalidatedBy = opts.invalidatedBy;
const closestLookup = this._lookupByNormalPath(normalPath, {
collectAncestors: ancestorsOfInput,
collectLinkPaths: invalidatedBy,
});
if (closestLookup.exists && isDirectory(closestLookup.node)) {
const maybeAbsolutePathMatch = this.#checkCandidateHasSubpath(
closestLookup.canonicalPath,
subpath,
opts.subpathType,
invalidatedBy,
null,
);
if (maybeAbsolutePathMatch != null) {
return {
absolutePath: maybeAbsolutePathMatch,
containerRelativePath: "",
};
}
} else {
if (
invalidatedBy &&
(!closestLookup.exists || !isDirectory(closestLookup.node))
) {
invalidatedBy.add(
this.#pathUtils.normalToAbsolute(
closestLookup.exists
? closestLookup.canonicalPath
: closestLookup.canonicalMissingPath,
),
);
}
if (
opts.breakOnSegment != null &&
!closestLookup.exists &&
closestLookup.missingSegmentName === opts.breakOnSegment
) {
return null;
}
}
let commonRoot = this.#rootNode;
let commonRootDepth = 0;
if (closestLookup.exists && closestLookup.ancestorOfRootIdx != null) {
commonRootDepth = closestLookup.ancestorOfRootIdx;
(0, _invariant.default)(
isDirectory(closestLookup.node),
"ancestors of the root must be directories",
);
commonRoot = closestLookup.node;
} else {
for (const ancestor of ancestorsOfInput) {
if (ancestor.ancestorOfRootIdx == null) {
break;
}
commonRootDepth = ancestor.ancestorOfRootIdx;
commonRoot = ancestor.node;
}
}
for (
let candidateIdx = ancestorsOfInput.length - 1;
candidateIdx >= commonRootDepth;
--candidateIdx
) {
const candidate = ancestorsOfInput[candidateIdx];
if (candidate.segmentName === opts.breakOnSegment) {
return null;
}
const maybeAbsolutePathMatch = this.#checkCandidateHasSubpath(
candidate.normalPath,
subpath,
opts.subpathType,
invalidatedBy,
{
ancestorOfRootIdx: candidate.ancestorOfRootIdx,
node: candidate.node,
pathIdx:
candidate.normalPath.length > 0
? candidate.normalPath.length + 1
: 0,
},
);
if (maybeAbsolutePathMatch != null) {
let prefixLength = commonRootDepth * 3;
for (let i = commonRootDepth; i <= candidateIdx; i++) {
prefixLength = normalPath.indexOf(
_path.default.sep,
prefixLength + 1,
);
}
const containerRelativePath = normalPath.slice(prefixLength + 1);
return {
absolutePath: maybeAbsolutePathMatch,
containerRelativePath,
};
}
}
let candidateNormalPath =
commonRootDepth > 0 ? normalPath.slice(0, 3 * commonRootDepth - 1) : "";
const remainingNormalPath = normalPath.slice(commonRootDepth * 3);
let nextNode = commonRoot;
let depthBelowCommonRoot = 0;
while (isDirectory(nextNode)) {
const maybeAbsolutePathMatch = this.#checkCandidateHasSubpath(
candidateNormalPath,
subpath,
opts.subpathType,
invalidatedBy,
null,
);
if (maybeAbsolutePathMatch != null) {
const rootDirParts = this.#pathUtils.getParts();
const relativeParts =
depthBelowCommonRoot > 0
? rootDirParts.slice(
-(depthBelowCommonRoot + commonRootDepth),
commonRootDepth > 0 ? -commonRootDepth : undefined,
)
: [];
if (remainingNormalPath !== "") {
relativeParts.push(remainingNormalPath);
}
return {
absolutePath: maybeAbsolutePathMatch,
containerRelativePath: relativeParts.join(_path.default.sep),
};
}
depthBelowCommonRoot++;
candidateNormalPath =
candidateNormalPath === ""
? ".."
: candidateNormalPath + _path.default.sep + "..";
nextNode = nextNode.get("..");
}
return null;
}
#checkCandidateHasSubpath(
normalCandidatePath,
subpath,
subpathType,
invalidatedBy,
start,
) {
const lookupResult = this._lookupByNormalPath(
this.#pathUtils.joinNormalToRelative(normalCandidatePath, subpath)
.normalPath,
{
collectLinkPaths: invalidatedBy,
},
);
if (
lookupResult.exists &&
isDirectory(lookupResult.node) === (subpathType === "d")
) {
return this.#pathUtils.normalToAbsolute(lookupResult.canonicalPath);
} else if (invalidatedBy) {
invalidatedBy.add(
this.#pathUtils.normalToAbsolute(
lookupResult.exists
? lookupResult.canonicalPath
: lookupResult.canonicalMissingPath,
),
);
}
return null;
}
*metadataIterator(opts) {
yield* this._metadataIterator(this.#rootNode, opts);
}
*_metadataIterator(rootNode, opts, prefix = "") {
for (const [name, node] of rootNode) {
if (
!opts.includeNodeModules &&
isDirectory(node) &&
name === "node_modules"
) {
continue;
}
const prefixedName =
prefix === "" ? name : prefix + _path.default.sep + name;
if (isDirectory(node)) {
yield* this._metadataIterator(node, opts, prefixedName);
} else if (isRegularFile(node) || opts.includeSymlinks) {
yield {
canonicalPath: prefixedName,
metadata: node,
baseName: name,
};
}
}
}
_normalizePath(relativeOrAbsolutePath) {
return _path.default.isAbsolute(relativeOrAbsolutePath)
? this.#pathUtils.absoluteToNormal(relativeOrAbsolutePath)
: this.#pathUtils.relativeToNormal(relativeOrAbsolutePath);
}
*#directoryNodeIterator(node, parent, ancestorOfRootIdx) {
if (ancestorOfRootIdx != null && ancestorOfRootIdx > 0 && parent) {
yield [
this.#pathUtils.getBasenameOfNthAncestor(ancestorOfRootIdx - 1),
parent,
];
}
yield* node.entries();
}
*_pathIterator(
iterationRootNode,
iterationRootParentNode,
ancestorOfRootIdx,
opts,
pathPrefix = "",
followedLinks = new Set(),
) {
const pathSep = opts.alwaysYieldPosix ? "/" : _path.default.sep;
const prefixWithSep = pathPrefix === "" ? pathPrefix : pathPrefix + pathSep;
for (const [name, node] of this.#directoryNodeIterator(
iterationRootNode,
iterationRootParentNode,
ancestorOfRootIdx,
)) {
if (opts.subtreeOnly && name === "..") {
continue;
}
const nodePath = prefixWithSep + name;
if (!isDirectory(node)) {
if (isRegularFile(node)) {
yield nodePath;
} else {
const nodePathWithSystemSeparators =
pathSep === _path.default.sep
? nodePath
: nodePath.replaceAll(pathSep, _path.default.sep);
const normalPathOfSymlink = _path.default.join(
opts.canonicalPathOfRoot,
nodePathWithSystemSeparators,
);
const resolved = this._lookupByNormalPath(normalPathOfSymlink, {
followLeaf: true,
});
if (!resolved.exists) {
continue;
}
const target = resolved.node;
if (!isDirectory(target)) {
yield nodePath;
} else if (
opts.recursive &&
opts.follow &&
!followedLinks.has(node)
) {
yield* this._pathIterator(
target,
resolved.parentNode,
resolved.ancestorOfRootIdx,
opts,
nodePath,
new Set([...followedLinks, node]),
);
}
}
} else if (opts.recursive) {
yield* this._pathIterator(
node,
iterationRootParentNode,
ancestorOfRootIdx != null && ancestorOfRootIdx > 0
? ancestorOfRootIdx - 1
: null,
opts,
nodePath,
followedLinks,
);
}
}
}
_resolveSymlinkTargetToNormalPath(symlinkNode, canonicalPathOfSymlink) {
const cachedResult = this.#cachedNormalSymlinkTargets.get(symlinkNode);
if (cachedResult != null) {
return cachedResult;
}
const literalSymlinkTarget = symlinkNode[_constants.default.SYMLINK];
(0, _invariant.default)(
typeof literalSymlinkTarget === "string",
"Expected symlink target to be populated.",
);
const absoluteSymlinkTarget = _path.default.resolve(
this.#rootDir,
canonicalPathOfSymlink,
"..",
literalSymlinkTarget,
);
const normalSymlinkTarget = _path.default.relative(
this.#rootDir,
absoluteSymlinkTarget,
);
const result = {
ancestorOfRootIdx:
this.#pathUtils.getAncestorOfRootIdx(normalSymlinkTarget),
normalPath: normalSymlinkTarget,
startOfBasenameIdx:
normalSymlinkTarget.lastIndexOf(_path.default.sep) + 1,
};
this.#cachedNormalSymlinkTargets.set(symlinkNode, result);
return result;
}
_getFileData(
filePath,
opts = {
followLeaf: true,
},
) {
const normalPath = this._normalizePath(filePath);
const result = this._lookupByNormalPath(normalPath, {
followLeaf: opts.followLeaf,
});
if (!result.exists || isDirectory(result.node)) {
return null;
}
return result.node;
}
_cloneTree(root) {
const clone = new Map();
for (const [name, node] of root) {
if (isDirectory(node)) {
clone.set(name, this._cloneTree(node));
} else {
clone.set(name, [...node]);
}
}
return clone;
}
}
exports.default = TreeFS;
Выполнить команду
Для локальной разработки. Не используйте в интернете!