From af52e37b37b616b7e563798e1440bcf9e544c88d Mon Sep 17 00:00:00 2001 From: Violet Yao Date: Wed, 18 Aug 2021 15:40:44 -0700 Subject: [PATCH] fix: forceIgnore does not work for `SFDX: Retrieve Source in Manifest from Org` in vscode extension (#413) * fix: forceIgnore does not work with retrieve manifest * fix: matchingContent subfolder --- src/client/metadataApiRetrieve.ts | 5 ++++- src/collections/componentSet.ts | 4 ++++ src/convert/metadataConverter.ts | 1 + src/convert/streams.ts | 20 +++++++++++++++++--- src/convert/types.ts | 1 + src/resolve/metadataResolver.ts | 3 +++ test/client/metadataApiRetrieve.test.ts | 16 ++++++++++++++++ test/mock/client/transferOperations.ts | 9 ++++++++- 8 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/client/metadataApiRetrieve.ts b/src/client/metadataApiRetrieve.ts index 8e1b86cf14..64d5b34d8e 100644 --- a/src/client/metadataApiRetrieve.ts +++ b/src/client/metadataApiRetrieve.ts @@ -216,6 +216,7 @@ export class MetadataApiRetrieve extends MetadataTransfer< type: 'merge', mergeWith: this.components.getSourceComponents(), defaultDirectory: pkg.outputDir, + forceIgnoredPaths: this.components.forceIgnoredPaths ?? new Set(), } : { type: 'directory', @@ -229,7 +230,9 @@ export class MetadataApiRetrieve extends MetadataTransfer< .getSourceComponents() .toArray(); const convertResult = await converter.convert(zipComponents, 'source', outputConfig); - components.push(...convertResult.converted); + if (convertResult) { + components.push(...convertResult.converted); + } } return new ComponentSet(components, registry); } diff --git a/src/collections/componentSet.ts b/src/collections/componentSet.ts index a544d0e417..12e59565b1 100644 --- a/src/collections/componentSet.ts +++ b/src/collections/componentSet.ts @@ -58,6 +58,7 @@ export class ComponentSet extends LazyCollection { */ public sourceApiVersion: string; public fullName?: string; + public forceIgnoredPaths?: Set; private logger: Logger; private registry: RegistryAccess; private components = new Map>(); @@ -137,6 +138,8 @@ export class ComponentSet extends LazyCollection { buildComponents(fsPaths, false); buildComponents(fsDeletePaths, true); + set.forceIgnoredPaths = resolver.forceIgnoredPaths; + return set; } @@ -192,6 +195,7 @@ export class ComponentSet extends LazyCollection { include: resolveIncludeSet, registry: options.registry, }); + result.forceIgnoredPaths = components.forceIgnoredPaths; for (const component of components) { result.add(component); } diff --git a/src/convert/metadataConverter.ts b/src/convert/metadataConverter.ts index 12f266e85c..00df8ef8d3 100644 --- a/src/convert/metadataConverter.ts +++ b/src/convert/metadataConverter.ts @@ -143,6 +143,7 @@ export class MetadataConverter { mergeSet.add(component.parent ?? component); } writer = new StandardWriter(output.defaultDirectory); + writer.forceIgnoredPaths = output.forceIgnoredPaths; break; } diff --git a/src/convert/streams.ts b/src/convert/streams.ts index 37ba3444ec..961cb274c1 100644 --- a/src/convert/streams.ts +++ b/src/convert/streams.ts @@ -6,13 +6,13 @@ */ import { Archiver, create as createArchive } from 'archiver'; import { createWriteStream } from 'fs'; -import { isAbsolute, join } from 'path'; +import { basename, dirname, isAbsolute, join } from 'path'; import { pipeline as cbPipeline, Readable, Transform, Writable } from 'stream'; import { promisify } from 'util'; import { SourceComponent, MetadataResolver } from '../resolve'; import { SfdxFileFormat, WriteInfo, WriterFormat } from './types'; import { ensureFileExists } from '../utils/fileSystemHandler'; -import { SourcePath, XML_DECL } from '../common'; +import { META_XML_SUFFIX, SourcePath, XML_DECL } from '../common'; import { ConvertContext } from './convertContext'; import { MetadataTransformerFactory } from './transformers'; import { JsonMap } from '@salesforce/ts-types'; @@ -20,7 +20,7 @@ import { j2xParser } from 'fast-xml-parser'; import { ComponentSet } from '../collections'; import { LibraryError } from '../errors'; import { RegistryAccess } from '../registry'; -import { Logger } from '@salesforce/core'; +import { fs, Logger } from '@salesforce/core'; export const pipeline = promisify(cbPipeline); export class ComponentReader extends Readable { @@ -126,6 +126,7 @@ export class ComponentConverter extends Transform { } export abstract class ComponentWriter extends Writable { + public forceIgnoredPaths?: Set = new Set(); protected rootDestination?: SourcePath; constructor(rootDestination?: SourcePath) { @@ -158,6 +159,19 @@ export class StandardWriter extends ComponentWriter { const fullDest = isAbsolute(info.output) ? info.output : join(this.rootDestination, info.output); + if (!fs.fileExistsSync(fullDest)) { + for (const ignoredPath of this.forceIgnoredPaths) { + if ( + dirname(ignoredPath).includes(dirname(fullDest)) && + basename(ignoredPath).includes(basename(fullDest)) + ) { + return; + } + } + } + if (this.forceIgnoredPaths.has(fullDest)) { + return; + } // if there are children, resolve each file. o/w just pick one of the files to resolve if (toResolve.length === 0 || chunk.component.type.children) { // This is a workaround for a server side ListViews bug where diff --git a/src/convert/types.ts b/src/convert/types.ts index f1c1139469..5df5390171 100644 --- a/src/convert/types.ts +++ b/src/convert/types.ts @@ -64,6 +64,7 @@ export type MergeConfig = { * Location to store components that aren't merged. */ defaultDirectory: SourcePath; + forceIgnoredPaths?: Set; }; /** diff --git a/src/resolve/metadataResolver.ts b/src/resolve/metadataResolver.ts index e64adc8984..eba9d7fd91 100644 --- a/src/resolve/metadataResolver.ts +++ b/src/resolve/metadataResolver.ts @@ -20,6 +20,7 @@ import { MetadataType } from '../registry'; * @internal */ export class MetadataResolver { + public forceIgnoredPaths: Set; private forceIgnore: ForceIgnore; private sourceAdapterFactory: SourceAdapterFactory; private tree: TreeContainer; @@ -33,6 +34,7 @@ export class MetadataResolver { this.registry = registry; this.tree = tree; this.sourceAdapterFactory = new SourceAdapterFactory(this.registry, tree); + this.forceIgnoredPaths = new Set(); } /** @@ -118,6 +120,7 @@ export class MetadataResolver { private resolveComponent(fsPath: string, isResolvingSource: boolean): SourceComponent { if (this.forceIgnore.denies(fsPath)) { // don't resolve the component if the path is denied + this.forceIgnoredPaths.add(fsPath); return; } const type = this.resolveType(fsPath); diff --git a/test/client/metadataApiRetrieve.test.ts b/test/client/metadataApiRetrieve.test.ts index 9afe2293f9..1557f68aa2 100644 --- a/test/client/metadataApiRetrieve.test.ts +++ b/test/client/metadataApiRetrieve.test.ts @@ -336,6 +336,7 @@ describe('MetadataApiRetrieve', async () => { type: 'merge', mergeWith: toRetrieve.getSourceComponents(), defaultDirectory: MOCK_DEFAULT_OUTPUT, + forceIgnoredPaths: new Set(), }) ).to.be.true; }); @@ -355,6 +356,21 @@ describe('MetadataApiRetrieve', async () => { expect(result).to.deep.equal(expected); }); + it('should construct a result object with no components when components are forceIgnored', async () => { + const toRetrieve = new ComponentSet([COMPONENT], mockRegistry); + toRetrieve.forceIgnoredPaths = new Set([COMPONENT.xml, COMPONENT.content]); + const { operation } = await stubMetadataRetrieve(env, { + toRetrieve, + merge: true, + successes: toRetrieve, + }); + + await operation.start(); + const result = await operation.pollStatus(); + + expect(result.components.size).to.equal(0); + }); + it('should construct a result object with no components when no components are retrieved', async () => { const toRetrieve = new ComponentSet([COMPONENT], mockRegistry); const { operation, response } = await stubMetadataRetrieve(env, { diff --git a/test/mock/client/transferOperations.ts b/test/mock/client/transferOperations.ts index b5510a6849..6aee0aec7f 100644 --- a/test/mock/client/transferOperations.ts +++ b/test/mock/client/transferOperations.ts @@ -258,6 +258,7 @@ export async function stubMetadataRetrieve( type: 'merge', mergeWith: retrievedComponents.getSourceComponents(), defaultDirectory: MOCK_DEFAULT_OUTPUT, + forceIgnoredPaths: retrievedComponents.forceIgnoredPaths ?? new Set(), }); converted = source; @@ -266,6 +267,7 @@ export async function stubMetadataRetrieve( type: 'merge', mergeWith: retrievedComponents.getSourceComponents(), defaultDirectory: pkg.outputDir, + forceIgnoredPaths: retrievedComponents.forceIgnoredPaths ?? new Set(), }) ); } else { @@ -297,7 +299,12 @@ export async function stubMetadataRetrieve( } const convertStub = sandbox.stub(MetadataConverter.prototype, 'convert'); outputConfigs.forEach((outputCfg) => { - convertStub.withArgs(match.any, 'source', outputCfg).resolves({ converted }); + const notForceIgnoredConverted = converted.filter( + (component) => !retrievedComponents.forceIgnoredPaths ?? [].includes(component.xml) + ); + convertStub + .withArgs(match.any, 'source', outputCfg) + .resolves({ converted: notForceIgnoredConverted }); }); return {