@rushstack/package-extractor
Version:
A library for bundling selected files and dependencies into a deployable package.
91 lines • 5.68 kB
JavaScript
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateLinksAction = void 0;
const node_path_1 = __importDefault(require("node:path"));
const node_core_library_1 = require("@rushstack/node-core-library");
const ts_command_line_1 = require("@rushstack/ts-command-line");
const Utils_1 = require("../../../../Utils");
const CreateLinksUtilities_1 = require("../../utilities/CreateLinksUtilities");
const constants_1 = require("../../utilities/constants");
const RemoveLinksAction_1 = require("./RemoveLinksAction");
async function createLinksAsync(terminal, targetRootFolder, extractorMetadataObject) {
await node_core_library_1.Async.forEachAsync(extractorMetadataObject.links, async (linkInfo) => {
// Link to the relative path for symlinks
const newLinkPath = node_path_1.default.join(targetRootFolder, linkInfo.linkPath);
const linkTargetPath = node_path_1.default.join(targetRootFolder, linkInfo.targetPath);
// Make sure the containing folder exists
await node_core_library_1.FileSystem.ensureFolderAsync(node_path_1.default.dirname(newLinkPath));
// NOTE: This logic is based on NpmLinkManager._createSymlink()
if (linkInfo.kind === 'folderLink') {
terminal.writeVerboseLine(`Creating linked folder at path "${newLinkPath}"`);
await node_core_library_1.FileSystem.createSymbolicLinkJunctionAsync({ newLinkPath, linkTargetPath });
}
else if (linkInfo.kind === 'fileLink') {
// Use hardlinks for Windows and symlinks for other platforms since creating a symbolic link
// requires administrator permission on Windows. This may cause unexpected behaviour for consumers
// of the hardlinked files. If this becomes an issue, we may need to revisit this.
terminal.writeVerboseLine(`Creating linked file at path "${newLinkPath}"`);
if (process.platform === 'win32') {
await node_core_library_1.FileSystem.createHardLinkAsync({ newLinkPath, linkTargetPath });
}
else {
await node_core_library_1.FileSystem.createSymbolicLinkFileAsync({ newLinkPath, linkTargetPath });
}
}
}, { concurrency: constants_1.MAX_CONCURRENCY });
}
async function realizeFilesAsync(terminal, targetRootFolder, extractorMetadataObject) {
await node_core_library_1.Async.forEachAsync(extractorMetadataObject.files, async (relativeFilePath) => {
const filePath = `${targetRootFolder}/${relativeFilePath}`;
const realFilePath = await node_core_library_1.FileSystem.getRealPathAsync(filePath);
if (!node_core_library_1.Path.isEqual(realFilePath, filePath)) {
// Delete the existing symlink and create a hardlink to the real file, since creating hardlinks
// is less overhead than copying the file.
terminal.writeVerboseLine(`Realizing file at path "${filePath}"`);
await node_core_library_1.FileSystem.deleteFileAsync(filePath);
await node_core_library_1.FileSystem.createHardLinkAsync({ newLinkPath: filePath, linkTargetPath: realFilePath });
}
}, { concurrency: constants_1.MAX_CONCURRENCY });
}
class CreateLinksAction extends ts_command_line_1.CommandLineAction {
constructor(terminal) {
super({
actionName: 'create',
summary: 'Create symlinks for extraction',
documentation: 'This action creates symlinks for the extraction process.'
});
this._terminal = terminal;
this._realizeFilesParameter = this.defineFlagParameter({
parameterLongName: constants_1.REALIZE_FILES_PARAMETER_NAME,
description: 'Realize files instead of creating symlinks'
});
this._linkBinsParameter = this.defineFlagParameter({
parameterLongName: constants_1.LINK_BINS_PARAMETER_NAME,
description: 'Create the .bin files for extracted packages'
});
}
async onExecuteAsync() {
const extractorMetadataObject = await (0, CreateLinksUtilities_1.getExtractorMetadataAsync)();
const realizeFiles = this._realizeFilesParameter.value;
const linkBins = this._linkBinsParameter.value;
this._terminal.writeLine(`Creating links for extraction at path "${constants_1.TARGET_ROOT_FOLDER}"`);
await (0, RemoveLinksAction_1.removeLinksAsync)(this._terminal, constants_1.TARGET_ROOT_FOLDER, extractorMetadataObject);
await createLinksAsync(this._terminal, constants_1.TARGET_ROOT_FOLDER, extractorMetadataObject);
if (realizeFiles) {
this._terminal.writeLine(`Realizing files for extraction at path "${constants_1.TARGET_ROOT_FOLDER}"`);
await realizeFilesAsync(this._terminal, constants_1.TARGET_ROOT_FOLDER, extractorMetadataObject);
}
if (linkBins) {
this._terminal.writeLine(`Linking bins for extraction at path "${constants_1.TARGET_ROOT_FOLDER}"`);
const extractedProjectFolderPaths = extractorMetadataObject.projects.map((project) => node_path_1.default.join(constants_1.TARGET_ROOT_FOLDER, project.path));
await (0, Utils_1.makeBinLinksAsync)(this._terminal, extractedProjectFolderPaths);
}
}
}
exports.CreateLinksAction = CreateLinksAction;
//# sourceMappingURL=CreateLinksAction.js.map
;