Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/commands/project/delete/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';

import { Interfaces } from '@oclif/core';
import { Lifecycle, Messages, Org, SfError } from '@salesforce/core';
import {
Expand Down Expand Up @@ -188,7 +187,12 @@ export class Source extends SfCommand<DeleteSourceJson> {
// if we didn't find any components to delete, let the user know and exit
this.styledHeader(tableHeader('Deleted Source'));
this.log('No results found');
return;
if (this.componentSet.forceIgnoredPaths?.size) {
// we have nothing in the CS, and something forceignored, let the user know they're trying to delete a forceignored file
const ignoredComponentPaths = Array.from(this.componentSet.forceIgnoredPaths).toString();
this.warn(`Attempting to delete metadata that conflicts with a .forceignore entry: ${ignoredComponentPaths}
Update the .forceignore file and try again.`);
}
}

// create a new ComponentSet and mark everything for deletion
Expand Down Expand Up @@ -285,7 +289,7 @@ export class Source extends SfCommand<DeleteSourceJson> {
*/
protected async resolveSuccess(): Promise<void> {
// if deploy failed restore the stashed files if they exist
if (this.deployResult?.response?.status !== RequestStatus.Succeeded) {
if (this.deployResult && this.deployResult.response?.status !== RequestStatus.Succeeded) {
process.exitCode = 1;
await Promise.all(
this.mixedDeployDelete.delete.map(async (file) => {
Expand Down
13 changes: 12 additions & 1 deletion test/commands/delete/source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
SourceComponent,
} from '@salesforce/source-deploy-retrieve';
import { Lifecycle, SfProject } from '@salesforce/core';
import { fromStub, stubInterface, stubMethod } from '@salesforce/ts-sinon';
import { fromStub, spyMethod, stubInterface, stubMethod } from '@salesforce/ts-sinon';
import { Config } from '@oclif/core';
import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup';
import { SfCommand } from '@salesforce/sf-plugins-core';
Expand Down Expand Up @@ -205,6 +205,17 @@ describe('project delete source', () => {
expect(rmStub.callCount).to.equal(2);
});

it('should warn if everything is forceignored', async () => {
buildComponentSetStub.restore();
const warnSpy = spyMethod($$.SANDBOX, SfCommand.prototype, 'warn');
buildComponentSetStub = stubMethod($$.SANDBOX, ComponentSetBuilder, 'build').resolves({
forceIgnoredPaths: new Set<string>('myPath'),
toArray: () => [],
});
await runDeleteCmd(['--metadata', 'ApexClass:MyClass', '--json', '-r']);
expect(warnSpy.calledOnce).to.be.true;
});

it('should pass along metadata', async () => {
const metadata = ['ApexClass:MyClass'];
await runDeleteCmd(['--metadata', metadata[0], '--json', '-r']);
Expand Down
Loading