UNPKG

salesforce-alm

Version:

This package contains tools, and APIs, for an improved salesforce.com developer experience.

602 lines (600 loc) 32.6 kB
"use strict"; /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ Object.defineProperty(exports, "__esModule", { value: true }); exports.AggregateSourceElement = void 0; const path = require("path"); const _ = require("lodash"); const srcDevUtil = require("../core/srcDevUtil"); const Messages = require("../messages"); const workspaceFileState_1 = require("./workspaceFileState"); const messages = Messages(); const MetadataRegistry = require("./metadataRegistry"); const almError = require("../core/almError"); const decompositionStrategyFactory_1 = require("./decompositionStrategy/decompositionStrategyFactory"); const workspaceElement_1 = require("./workspaceElement"); const metadataTypeFactory_1 = require("./metadataTypeFactory"); const folderMetadataType_1 = require("./metadataTypeImpl/folderMetadataType"); const PathUtils = require("./sourcePathUtil"); const sourceUtil_1 = require("./sourceUtil"); const core_1 = require("@salesforce/core"); const sourceLocations_1 = require("./sourceLocations"); /** * Class used to manage top-level metadata * Examples of top-level metadata types include: ApexClass, CustomObject, StaticResource, etc. * * For compound metadata requiring de/recomposition, this facade is the point of entry for * decomposition/re-composition from other code. No client code should reference any other * internal implementation classes. If this class proves inadequate for future needs then it should * be extended and the internal implementation classes modified to support the new requirements. * * This class is agnostic wrt how the decomposition of the source metadata file is * performed, including the nature of the aggregated and decomposed files, and also * how the decomposed files are represented in the workspace. These decisions are * delegated to the strategies configured in the metadata registry for the type. */ class AggregateSourceElement { /** * @param aggregateMetadataType - this is the type for the top-level parent metadata - e.g. ApexClass, CustomObject, etc. * @param aggregateFullName - this is the name of the top-level parent metadata * @param aggregateMetadataFilePath - this is the full file path to the top-level parent metadata * @param metadataRegistry */ constructor(aggregateMetadataType, aggregateFullName, aggregateMetadataFilePath, metadataRegistry) { /** * * @param sourcePath Source workspace filepath * @param mdapiPath Temporary mdapiDir filepath * @returns {{sourcePath: *, mdapiPath: *}} * @private */ this.createTranslation = function (sourcePath, mdapiPath) { return { sourcePath, mdapiPath }; }; this.metadataType = aggregateMetadataType; this.workspaceVersion = null; // fill this in when the workspace version is known this.metadataRegistry = metadataRegistry; // my hope is to be able to get rid of this when typeDefs become first class this.aggregateFullName = aggregateFullName; this.metadataFilePath = aggregateMetadataFilePath; this.packageName = core_1.SfdxProject.getInstance().getPackageNameFromPath(this.metadataFilePath); this.decompStrategy = decompositionStrategyFactory_1.DecompositionStrategyFactory.newDecompositionStrategy(this.metadataType.getDecompositionConfig()); this.workspaceStrategy = decompositionStrategyFactory_1.DecompositionStrategyFactory.newDecompositionWorkspaceStrategy(this.metadataType.getDecompositionConfig()); this.commitStrategy = decompositionStrategyFactory_1.DecompositionStrategyFactory.newDecompositionCommitStrategy(this.metadataType.getDecompositionConfig()); this.contentStrategy = decompositionStrategyFactory_1.DecompositionStrategyFactory.newContentStrategy(this.metadataType, this.metadataRegistry, this.workspaceVersion); this.workspaceElements = []; this.pendingDeletedWorkspaceElements = []; this.deleted = null; } getMetadataType() { return this.metadataType; } static getKeyFromMetadataNameAndFullName(aggregateMetadataName, aggregateFullName) { return `${aggregateMetadataName}__${aggregateFullName}`; } getKey() { return AggregateSourceElement.getKeyFromMetadataNameAndFullName(this.getMetadataName(), this.getAggregateFullName()); } /** * Gets the metadata workspace path that would be in use if this type were not transformed. * The locations of associated decomposed/non-decomposed content and metadata files can be inferred from this name. * * @returns {string} */ getMetadataFilePath() { return this.metadataFilePath; } getAggregateFullName() { return this.aggregateFullName; } getMetadataName() { return this.metadataType.getMetadataName(); } getPackageName() { return this.packageName; } /** * Returns all paths to workspace source files matching the given metadata type and fullName * * @param metadataTypeName * @param fullNameForPath * @returns {string[]} */ getWorkspacePathsForTypeAndFullName(metadataTypeName, fullNameForPath) { const contentPathsForFullName = this.getContentWorkspacePathsForTypeAndFullName(metadataTypeName, fullNameForPath); const metadataPathsForFullName = this.getMetadataWorkspacePathsForTypeAndFullName(metadataTypeName, fullNameForPath); return contentPathsForFullName.concat(metadataPathsForFullName); } getContentWorkspacePathsForTypeAndFullName(metadataTypeName, fullNameForPath) { // get content file paths const allContentPaths = this.getContentPaths(this.getMetadataFilePath()); return allContentPaths.filter((contentPath) => { const contentMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromSourcePath(contentPath, this.metadataRegistry); const fullName = contentMetadataType.getFullNameFromFilePath(contentPath); return fullName === fullNameForPath; }); } getMetadataWorkspacePathsForTypeAndFullName(metadataTypeName, fullNameForPath) { const wantedMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(metadataTypeName, this.metadataRegistry); const allDecomposedPaths = this.getMetadataPaths(this.getMetadataFilePath()); return allDecomposedPaths.filter((decomposedPath) => { const decomposedMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromSourcePath(decomposedPath, this.metadataRegistry); if (decomposedMetadataType.constructor === wantedMetadataType.constructor) { const decomposedFullName = decomposedMetadataType.getFullNameFromFilePath(decomposedPath); return fullNameForPath === decomposedFullName; } return false; }); } addWorkspaceElement(workspaceElement) { this.workspaceElements.push(workspaceElement); } /** * Returns the collection of workspace elements associated with this aggregate source element * * @returns {WorkspaceElement[]} */ getWorkspaceElements() { return this.workspaceElements; } /** * returns the collection of deleted workspace elements associated with this aggregate source element * * @returns {WorkspaceElement[]} */ getPendingDeletedWorkspaceElements() { return this.pendingDeletedWorkspaceElements; } /** * Adds the given workspace element to a collection to be processed during commit * * @param deletedWorkspaceElement */ addPendingDeletedWorkspaceElement(deletedWorkspaceElement) { this.pendingDeletedWorkspaceElements.push(deletedWorkspaceElement); } isDeleted() { if (!_.isNil(this.deleted)) { return this.deleted; } else { return this.isAggregateSourceElementDeleted(); } } /** * If the workspace is in an inconsistent state, where a metadata file was deleted but not the content files, * or the aura bundle metadata file was deleted but not the whole bundle, then throw an error * * @param workspaceElement */ validateIfDeletedWorkspaceElement(workspaceElement) { if (workspaceElement.getState() === workspaceFileState_1.WorkspaceFileState.DELETED) { const contentPaths = this.metadataType.hasContent() ? this.getContentPaths(this.getMetadataFilePath()) : []; // If the metadata file was deleted and not the content file, throw an error // Or if the container path for the fine-grained item was deleted but other decomposed items exist, throw an error if (workspaceElement.getSourcePath() === this.getContainerPath()) { const allDecomposedPaths = this.getMetadataPaths(this.getMetadataFilePath()); if ((this.metadataType.hasContent() && contentPaths.length !== 0) || allDecomposedPaths.length !== 0) { if (!this.decompStrategy.isComposable()) { throw almError('MissingMetadataFile', [workspaceElement.getSourcePath()]); } else { if (!this.getMetadataType().isStandardMember(workspaceElement.getFullName())) { throw almError('MissingMetadataFile', [workspaceElement.getSourcePath()]); } } } } this.metadataType.validateDeletedContentPath(workspaceElement.getSourcePath(), contentPaths, this.metadataRegistry); } } getContainerPath() { return this.workspaceStrategy.getContainerPath(this.getMetadataFilePath(), this.metadataType.getExt()); } isAggregateSourceElementDeleted() { let isDeleted = false; this.getWorkspaceElements().forEach((workspaceElement) => { this.validateIfDeletedWorkspaceElement(workspaceElement); if (workspaceElement.getState() === workspaceFileState_1.WorkspaceFileState.DELETED) { const deletedPath = workspaceElement.getSourcePath(); // Does the deleted path item match the object meta file path? // For most bundle types the container path is the path to the directory containing the bundle if (deletedPath.includes(this.getContainerPath())) { isDeleted = true; // Delete any remaining empty paths for composable entities. if (this.decompStrategy.isComposable()) { const metadataPaths = this.getMetadataPaths(this.getMetadataFilePath()); if (!metadataPaths || metadataPaths.length === 0) { PathUtils.cleanEmptyDirs(path.resolve(this.getMetadataFilePath(), '..')); } } } const deletedPathIsAContentPath = this.metadataType.isContentPath(deletedPath); // This would be akin to deleting an apex class .cls file. if (deletedPathIsAContentPath) { const crucialContentStillExists = this.metadataType.mainContentFileExists(this.getMetadataFilePath()); if (crucialContentStillExists) { isDeleted = false; } else { if (srcDevUtil.pathExistsSync(this.getMetadataFilePath())) { this.markForDelete(); } } } } }); return isDeleted; } /** * Flags this aggregate source element as deleted and marks all of its associated workspace elements as deleted */ markForDelete() { this.deleted = true; // eslint-disable-next-line @typescript-eslint/no-shadow const path = this.getMetadataFilePath(); const metadataPathsToDelete = this.getMetadataPaths(path); const contentPathsToDelete = this.getContentPaths(path); const allPaths = metadataPathsToDelete.concat(contentPathsToDelete); allPaths.forEach((deletedPath) => { const deletedMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromSourcePath(deletedPath, this.metadataRegistry); const fullNameForPath = deletedMetadataType.getFullNameFromFilePath(deletedPath); const deleteSupported = deletedMetadataType.deleteSupported(fullNameForPath); const deletedWorkspaceElement = new workspaceElement_1.WorkspaceElement(deletedMetadataType.getMetadataName(), fullNameForPath, deletedPath, workspaceFileState_1.WorkspaceFileState.DELETED, deleteSupported); this.addPendingDeletedWorkspaceElement(deletedWorkspaceElement); const nonDecomposedElementsIndex = sourceLocations_1.SourceLocations.nonDecomposedElementsIndex; // SourceLocations aren't available for source:delete. nonDecomposedElementsIndex is // only for special handling of CustomLabels for push/pull. if (nonDecomposedElementsIndex) { const elements = nonDecomposedElementsIndex.getElementsByMetadataFilePath(path); if (elements.length === 1) { nonDecomposedElementsIndex.deleteEntryBySourcePath(path); } } }); } /** * Gets the list of existing decomposed and non-decomposed metadata files for the given source metadata entity. * * @param metadataFilePath the workspace path that would be in use if this type were not transformed. * The locations of the actual decomposed files can be inferred from this name. This is a proxy for all * of decomposed files. * @returns {string[]} the list of existing decomposed files for the given source metadata entity */ getMetadataPaths(metadataFilePath) { const paths = []; const containerPath = this.workspaceStrategy.getContainerPath(metadataFilePath, this.metadataType.getExt()); if (!_.isNil(containerPath) && srcDevUtil.pathExistsSync(containerPath)) { paths.push(containerPath); } const decompositionPaths = this.workspaceStrategy.findDecomposedPaths(metadataFilePath, this.metadataType.getExt()); for (const decomposedSubtypeConfig of decompositionPaths.keys()) { for (const decompositionPath of decompositionPaths.get(decomposedSubtypeConfig)) { paths.push(decompositionPath); } } return paths; } /** * Gets all of the workspace paths to composed and nondecomposed content files associated with this aggregateSourceElement * * @param metadataFilePath * @returns {any} */ getContentPaths(metadataFilePath) { if (this.metadataType.hasContent()) { return this.contentStrategy.getContentPaths(metadataFilePath); } return []; } /** * Commits changes to the workspace * * @param manifest * @param unsupportedMimeTypes - the list of non-allow-listed static resource mime types * @param forceoverwrite * @returns {Array[]} */ async commit(manifest, unsupportedMimeTypes, forceoverwrite = false) { const newPaths = []; const updatedPaths = []; const deletedPaths = []; const dupPaths = []; this.commitDeletes(deletedPaths); if (!_.isNil(this.retrievedMetadataPath)) { await this.commitMetadata(newPaths, updatedPaths, deletedPaths, dupPaths, manifest, forceoverwrite); } if (this.metadataType.hasContent() && !_.isNil(this.retrievedContentPaths)) { await this.commitContent(newPaths, updatedPaths, deletedPaths, dupPaths, unsupportedMimeTypes, forceoverwrite); } // associate committed source to sourceElement this.addCorrespondingWorkspaceElements(newPaths, workspaceFileState_1.WorkspaceFileState.NEW); this.addCorrespondingWorkspaceElements(updatedPaths, workspaceFileState_1.WorkspaceFileState.CHANGED); this.addCorrespondingWorkspaceElements(deletedPaths, workspaceFileState_1.WorkspaceFileState.DELETED); this.addCorrespondingWorkspaceElements(dupPaths, workspaceFileState_1.WorkspaceFileState.DUP); // adding the empty folder must come after the creation of all corresponding workspace elements this.addEmptyFolder(); return [newPaths, updatedPaths, deletedPaths]; } /** * Delete workspace elements from the workspace * * @param deletedPaths */ commitDeletes(deletedPaths) { this.pendingDeletedWorkspaceElements // Need a new array so the pendingDeletedWorkspaceElements order is not modified. // It's probably not needed but this could create down stream problems if the order is changed. .slice() // Map the array into array of source paths .map((value) => value.getSourcePath()) // Sort it into delete order such that /foo gets deleted after /foo/bar.txt .sort(PathUtils.deleteOrderComparator) .forEach((deletedWorkspaceElementSourcePath) => { srcDevUtil.deleteIfExistsSync(deletedWorkspaceElementSourcePath); deletedPaths.push(deletedWorkspaceElementSourcePath); }); } async commitMetadata(newPaths, updatedPaths, deletedPaths, dupPaths, manifest, forceoverwrite) { const [newMetaPaths, updatedMetaPaths, deletedMetaPaths, dupMetaPaths] = await this.decomposeMetadata(this.retrievedMetadataPath, this.getMetadataFilePath(), manifest, forceoverwrite); newPaths.push(...newMetaPaths); updatedPaths.push(...updatedMetaPaths); deletedPaths.push(...deletedMetaPaths); dupPaths.push(...dupMetaPaths); } async commitContent(newPaths, updatedPaths, deletedPaths, dupPaths, unsupportedMimeTypes, forceoverwrite) { const [newContentPaths, updatedContentPaths, deletedContentPaths, dupContentPaths] = await this.contentStrategy.saveContent(this.getMetadataFilePath(), this.retrievedContentPaths, this.retrievedMetadataPath, this.isDuplicate, unsupportedMimeTypes, forceoverwrite); newPaths.push(...newContentPaths); updatedPaths.push(...updatedContentPaths); deletedPaths.push(...deletedContentPaths); dupPaths.push(...dupContentPaths); } addEmptyFolder() { if (this.metadataType.isFolderType()) { const folderPath = folderMetadataType_1.FolderMetadataType.createEmptyFolder(this.getWorkspaceElements(), this.getMetadataFilePath(), this.getMetadataType().getExt()); if (folderPath) { this.addWorkspaceElement(new workspaceElement_1.WorkspaceElement(this.getMetadataName(), this.aggregateFullName, folderPath, workspaceFileState_1.WorkspaceFileState.NEW, true)); } } } addCorrespondingWorkspaceElements(filePaths, state) { filePaths.forEach((filePath) => { let tempFilePath = filePath; if (tempFilePath.endsWith('.dup')) { // if we are dealing with a duplicate file do all the calculations as if it wasn't a dup tempFilePath = tempFilePath.substring(0, tempFilePath.length - 4); } const workspaceElementMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromSourcePath(tempFilePath, this.metadataRegistry); const workspaceElementFullName = workspaceElementMetadataType.getFullNameFromFilePath(tempFilePath); const deleteSupported = workspaceElementMetadataType.deleteSupported(workspaceElementFullName); const workspaceElement = new workspaceElement_1.WorkspaceElement(workspaceElementMetadataType.getMetadataName(), workspaceElementFullName, filePath, state, deleteSupported); this.addWorkspaceElement(workspaceElement); }); } checkForDuplicates() { if (this.metadataType.entityExistsInWorkspace(this.metadataFilePath)) { this.isDuplicate = true; } } /** * Gets the translation objects for copying source from the workspace to the metadata API formatted directory * * @param mdDir * @param tmpDir * @param unsupportedMimeTypes - the list of non-whitelisted static resource mime types * @param forceIgnore * @returns {Array} */ async getFilePathTranslations(mdDir, tmpDir, unsupportedMimeTypes, forceIgnore) { let filePathTranslations = []; if (this.metadataType.hasContent()) { try { filePathTranslations = await this.getContentPathTranslations(mdDir, unsupportedMimeTypes, forceIgnore); } catch (error) { if (error.message) { throw new core_1.SfdxError(error.message || error, 'RESOURCE_NOT_FOULD'); } else { throw core_1.SfdxError.create('salesforce-alm', 'source', 'MetadataFileDoesNotExist', [error]); } } } if (this.metadataType.shouldGetMetadataTranslation()) { const metadataPathTranslation = await this.getMetadataPathTranslation(tmpDir, mdDir); filePathTranslations.push(metadataPathTranslation); } return filePathTranslations; } getContentPathTranslations(mdDir, unsupportedMimeTypes, forceIgnore) { return this.metadataType .getOriginContentPathsForSourceConvert(this.getMetadataFilePath(), this.workspaceVersion, unsupportedMimeTypes, forceIgnore) .then((originContentPaths) => originContentPaths.map((originContentPath) => { const mdapiContentPath = this.metadataType.getMdapiContentPathForSourceConvert(originContentPath, this.aggregateFullName, mdDir); if (!originContentPath && this.metadataType.hasContent()) { throw core_1.SfdxError.create('salesforce-alm', 'source', 'MissingComponentOrResource', [mdapiContentPath]); } return this.createTranslation(originContentPath, mdapiContentPath); })); } async getMetadataPathTranslation(tmpDir, mdDir) { const mdFilePath = this.getMetadataFilePath(); // For non-decomposed metadata, use the file from the source dir. For decomposed metadata, // compose it to the tmpDir. const composedPath = this.decompStrategy.isComposable() ? await this.composeMetadata(mdFilePath, tmpDir) : null; const workspacePathToMetadata = !_.isNil(composedPath) ? composedPath : mdFilePath; const mdapiMetadataPath = this.metadataType.getMdapiMetadataPath(mdFilePath, this.getAggregateFullName(), mdDir); return this.createTranslation(workspacePathToMetadata, mdapiMetadataPath); } /** * Composes a single metadata file from one or more files each representing a part of the whole. * It is important to understand that this does <b>not</b> have to be an mdapi xml file, even though * it usually will be. That determination will be driven by a type-specific configuration. * * @param metadataFilePath the workspace path that would be in use if this type were not transformed. * The locations of the actual decomposed files can be inferred from this name. This is a proxy for all * of decomposed files. * @param tmpDir temporary directory to hold the composed metadata file outside of the workspace. * @returns {string} the path of composed metadata file. */ // eslint-disable-next-line @typescript-eslint/require-await async composeMetadata(metadataFilePath, tmpDir) { let container; const containerPath = this.workspaceStrategy.getContainerPath(metadataFilePath, this.metadataType.getExt()); if (!_.isNil(containerPath) && this.includeDecomposition(containerPath)) { if (!srcDevUtil.pathExistsSync(containerPath)) { const err = new Error(); const metaExtIndex = containerPath.indexOf(MetadataRegistry.getMetadataFileExt()); const pathWithoutMetaExt = containerPath.substring(0, metaExtIndex); if (srcDevUtil.pathExistsSync(pathWithoutMetaExt) && !this.metadataType.hasContent()) { err['message'] = messages.getMessage('MissingMetadataExtension', [pathWithoutMetaExt, containerPath]); err['name'] = 'Expected Metadata Extension'; } else { err['message'] = messages.getMessage('MissingMetadataFileWithMetaExt', containerPath); err['name'] = 'Missing Metadata File'; } throw err; } else { container = this.decompStrategy.newContainerDocument(this.metadataType.getMetadataName()); try { container.setRepresentation(core_1.fs.readFileSync(containerPath, 'utf8')); } catch (e) { throw sourceUtil_1.checkForXmlParseError(containerPath, e); } } } const decompositions = new Map(); const decompositionPaths = this.workspaceStrategy.findDecomposedPaths(metadataFilePath, this.metadataType.getExt()); for (const decomposedSubtypeConfig of decompositionPaths.keys()) { for (const decompositionPath of decompositionPaths.get(decomposedSubtypeConfig)) { if (this.includeDecomposition(decompositionPath)) { const decomposition = this.decompStrategy.newDecompositionDocument(decomposedSubtypeConfig.metadataName); try { decomposition.setRepresentation(core_1.fs.readFileSync(decompositionPath, 'utf8')); } catch (e) { throw sourceUtil_1.checkForXmlParseError(decompositionPath, e); } if (_.isNil(decompositions.get(decomposedSubtypeConfig))) { decompositions.set(decomposedSubtypeConfig, []); } decompositions.get(decomposedSubtypeConfig).push(decomposition); } } } const composed = this.decompStrategy.compose(container, decompositions); const composedPath = this.getComposedFilePath(tmpDir); srcDevUtil.ensureDirectoryExistsSync(path.dirname(composedPath)); core_1.fs.writeFileSync(composedPath, composed.getRepresentation()); return composedPath; } includeDecomposition(decompositionFilePath) { if (this.metadataType.getDecompositionConfig().useSparseComposition) { const candidateElement = this.workspaceElements.find((workspaceElement) => workspaceElement.getSourcePath() === decompositionFilePath && (workspaceElement.getState() == workspaceFileState_1.WorkspaceFileState.NEW || workspaceElement.getState() == workspaceFileState_1.WorkspaceFileState.CHANGED)); return !_.isNil(candidateElement); } else { return true; } } /** * * @param sourceFilePath an aggregated file, typically an mdapi xml file * @param metadataFilePath the workspace path that would be in use if this type were not transformed. * The locations of the actual decomposed files can be inferred from this name. This is a proxy for all * of decomposed files. * @param manifest * @returns {[string[], string[], string[]]} a triplet containing a list of new, updated, and deleted workspace paths for the decomposed files. */ async decomposeMetadata(sourceFilePath, metadataFilePath, manifest, forceoverwrite = false) { const composed = this.decompStrategy.newComposedDocument(this.metadataType.getDecompositionConfig().metadataName); try { composed.setRepresentation(core_1.fs.readFileSync(sourceFilePath, 'utf8')); } catch (e) { throw sourceUtil_1.checkForXmlParseError(sourceFilePath, e); } let container; let decompositions; [container, decompositions] = this.decompStrategy.decompose(composed, this.metadataType.getAggregateFullNameFromFilePath(metadataFilePath), manifest, this.metadataType); const documents = this.getPaths(metadataFilePath, container, decompositions); const existingPaths = this.getMetadataPaths(metadataFilePath); return this.commitStrategy.commit(documents, existingPaths, this.isDuplicate, forceoverwrite); } getComposedFilePath(tmpDir) { return this.metadataType.getAggregateMetadataPathInDir(tmpDir, this.getAggregateFullName()); } getPaths(metadataFilePath, container, decompositions) { const paths = new Map(); const containerPath = this.workspaceStrategy.getContainerPath(metadataFilePath, this.metadataType.getExt()); if (!_.isNil(containerPath)) { if (!_.isNil(container)) { paths.set(containerPath, container); } } for (const decomposedSubtypeConfig of decompositions.keys()) { for (const decomposition of decompositions.get(decomposedSubtypeConfig)) { const annotation = decomposition.getAnnotation(); const sourceDir = this.getSourceDir(annotation, metadataFilePath, decomposedSubtypeConfig); /** * We want to ignore paths that belong to a package other than the package we're processing. * For example, when pulling a CustomObject in PackageA we want to ignore any CustomFields that * belong to PackageB */ if (this.shouldIgnorePath(sourceDir)) { continue; } const fileName = this.workspaceStrategy.getDecomposedFileName(annotation, decomposedSubtypeConfig); const decomposedPath = path.join(sourceDir, fileName); paths.set(decomposedPath, decomposition); } } return paths; } /** * Returns the source dir into which metadata will be decomposed. * It first tries to find an existing directory based on the annotation * If that directory does not exist, if will find the directory based on * the metadata file path * * @param annotation * @param metadataFilePath * @param decomposedSubtypeConfig */ getSourceDir(annotation, metadataFilePath, decomposedSubtypeConfig) { const existingDir = this.workspaceStrategy.getDecomposedSubtypeDirFromAnnotation(annotation, this.metadataType.getMetadataName(), this.aggregateFullName, decomposedSubtypeConfig); if (existingDir) { return existingDir; } else { return this.workspaceStrategy.getDecomposedSubtypeDirFromMetadataFile(metadataFilePath, this.metadataType.getExt(), decomposedSubtypeConfig); } } /** * Returns true if the provided path does not belong to the active package (that is, the package we're in the process of pulling) * For example, when pulling a CustomObject in PackageA, we don't want to update any CustomFields on that object that belong * to PackageB. * For a mdapi:convert, the pkgName should be null. The active package is set by the mdapiConvertCommand to be null as well * so this function returns false (meaning the path is not ignored, which is what we want). There are no package directories * for mdapi:convert and source:convert. */ shouldIgnorePath(sourceDir) { const activePackage = core_1.SfdxProject.getInstance().getActivePackage(); const activePackageName = activePackage ? activePackage.name : activePackage; if (!activePackageName) { return false; } const pkgName = core_1.SfdxProject.getInstance().getPackageNameFromPath(sourceDir); return pkgName !== activePackageName; } } exports.AggregateSourceElement = AggregateSourceElement; //# sourceMappingURL=aggregateSourceElement.js.map