From 1304bbe9a5f99afba25395bca589e3b43eb50a51 Mon Sep 17 00:00:00 2001 From: David First Date: Tue, 3 Jan 2023 16:46:42 -0500 Subject: [PATCH] fix(checkout): do not suggest using --entire-lane flag when the new components were soft-removed --- e2e/harmony/lanes/lanes.e2e.ts | 34 +++++++++++++++++-- .../checkout/checkout.main.runtime.ts | 12 +++++-- scopes/scope/scope/scope.main.runtime.ts | 12 +++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/e2e/harmony/lanes/lanes.e2e.ts b/e2e/harmony/lanes/lanes.e2e.ts index b3442f60a710..9388b108ca09 100644 --- a/e2e/harmony/lanes/lanes.e2e.ts +++ b/e2e/harmony/lanes/lanes.e2e.ts @@ -1346,6 +1346,8 @@ describe('bit lane command', function () { }); }); describe('getting new components from the lane', () => { + let firstWorkspaceAfterExport: string; + let secondWorkspace: string; before(() => { helper.scopeHelper.setNewLocalAndRemoteScopes(); helper.command.createLane(); @@ -1356,23 +1358,49 @@ describe('bit lane command', function () { helper.scopeHelper.reInitLocalScope(); helper.scopeHelper.addRemoteScope(); helper.command.importLane('dev'); - const secondWorkspace = helper.scopeHelper.cloneLocalScope(); + secondWorkspace = helper.scopeHelper.cloneLocalScope(); helper.scopeHelper.getClonedLocalScope(firstWorkspace); helper.fixtures.populateComponents(2); helper.command.snapAllComponentsWithoutBuild(); helper.command.export(); + firstWorkspaceAfterExport = helper.scopeHelper.cloneLocalScope(); helper.scopeHelper.getClonedLocalScope(secondWorkspace); helper.command.import(); }); - it('bit checkout without --entire-lane flag', () => { - helper.command.checkoutHead('--skip-dependency-installation'); + it('bit checkout without --entire-lane flag should not add the component and should suggest using --entire-lane flag', () => { + const output = helper.command.checkoutHead('--skip-dependency-installation'); const list = helper.command.listParsed(); expect(list).to.have.lengthOf(1); + expect(output).to.have.string('use --entire-lane flag to add them'); }); it('bit checkout with --entire-lane flag', () => { helper.command.checkoutHead('--entire-lane --skip-dependency-installation'); const list = helper.command.listParsed(); expect(list).to.have.lengthOf(2); }); + describe('when the new component is soft-removed', () => { + let beforeCheckout: string; + before(() => { + helper.scopeHelper.getClonedLocalScope(firstWorkspaceAfterExport); + helper.command.removeComponent('comp2', '--soft'); + helper.fs.writeFile('comp1/index.js', ''); // remove the comp2 dependency from the code + helper.command.snapAllComponentsWithoutBuild(); + helper.command.export(); + helper.scopeHelper.getClonedLocalScope(secondWorkspace); + helper.command.import(); + beforeCheckout = helper.scopeHelper.cloneLocalScope(); + }); + it('bit checkout without --entire-lane flag, should not suggest adding it', () => { + const output = helper.command.checkoutHead('--skip-dependency-installation'); + expect(output).to.not.have.string('use --entire-lane flag to add them'); + expect(output).to.not.have.string('comp2'); + }); + it('bit checkout with --entire-lane flag should not add it', () => { + helper.scopeHelper.getClonedLocalScope(beforeCheckout); + helper.command.checkoutHead('--entire-lane --skip-dependency-installation'); + const list = helper.command.listParsed(); + expect(list).to.have.lengthOf(1); + }); + }); }); }); diff --git a/scopes/component/checkout/checkout.main.runtime.ts b/scopes/component/checkout/checkout.main.runtime.ts index 765b9800a18f..966e05704afb 100644 --- a/scopes/component/checkout/checkout.main.runtime.ts +++ b/scopes/component/checkout/checkout.main.runtime.ts @@ -144,8 +144,7 @@ export class CheckoutMain { const compsNewFromLane = await Promise.all( newFromLane.map((id) => consumer.loadComponentWithDependenciesFromModel(id._legacy)) ); - const compsNewFromLaneNotDeleted = compsNewFromLane.filter((c) => !c.component.removed); - componentsWithDependencies.push(...compsNewFromLaneNotDeleted); + componentsWithDependencies.push(...compsNewFromLane); newFromLaneAdded = true; } } @@ -253,7 +252,14 @@ export class CheckoutMain { const laneBitIds = lane.toBitIds(); const newIds = laneBitIds.filter((bitId) => !ids.find((id) => id._legacy.isEqualWithoutVersion(bitId))); const newComponentIds = await this.workspace.resolveMultipleComponentIds(newIds); - return newComponentIds; + const nonRemovedNewIds: ComponentID[] = []; + await Promise.all( + newComponentIds.map(async (id) => { + const isRemoved = await this.workspace.scope.isComponentRemoved(id); + if (!isRemoved) nonRemovedNewIds.push(id); + }) + ); + return nonRemovedNewIds; } private async getComponentStatusBeforeMergeAttempt( diff --git a/scopes/scope/scope/scope.main.runtime.ts b/scopes/scope/scope/scope.main.runtime.ts index 15f9297d0dd3..a4468c5c95f7 100644 --- a/scopes/scope/scope/scope.main.runtime.ts +++ b/scopes/scope/scope/scope.main.runtime.ts @@ -1074,6 +1074,18 @@ needed-for: ${neededFor || ''}`); return StagedConfig.load(this.path, this.logger, currentLaneId); } + /** + * wether a component is soft-removed. + * the version is required as it can be removed on a lane. in which case, the version is the head in the lane. + */ + async isComponentRemoved(id: ComponentID): Promise { + const version = id.version; + if (!version) throw new Error(`isComponentRemoved expect to get version, got ${id.toString()}`); + const modelComponent = await this.legacyScope.getModelComponent(id._legacy); + const versionObj = await modelComponent.loadVersion(version, this.legacyScope.objects); + return versionObj.isRemoved(); + } + /** * resolve a component ID. * @param id component ID.