Skip to content

Commit c52f8a8

Browse files
L-Quniclantonoctogonz
authored
[rush] Follow-ups to #5123 (#5183)
* Follow-ups to #5123 * rush change * chore: update snapshot * fix: typo * chore: manually delete package when installing * fix: comments * Update libraries/rush-lib/src/cli/actions/BridgePackageAction.ts Co-authored-by: Ian Clanton-Thuon <iclanton@users.noreply.github.com> * fix: comments * fix: comments * chore: update snapshot * Update libraries/rush-lib/src/cli/actions/BridgePackageAction.ts Co-authored-by: Ian Clanton-Thuon <iclanton@users.noreply.github.com> * Update libraries/rush-lib/src/utilities/HotlinkManager.ts Co-authored-by: Ian Clanton-Thuon <iclanton@users.noreply.github.com> * chore: read subspace from cwd * fix: resolve comments * optimize error message * fix: resolve comments * Fix an issue where BridgePackageAction failed when rushConfiguration was missing * Fix a floating promise causing Jest to fail (why didn't ESLint catch this??) * Fix an issue where defineChoiceListParameter() was provided with nondeterministic choices and failed when the list was empty --------- Co-authored-by: Ian Clanton-Thuon <iclanton@users.noreply.github.com> Co-authored-by: Pete Gonzalez <4673363+octogonz@users.noreply.github.com>
1 parent 9a59d8b commit c52f8a8

8 files changed

Lines changed: 188 additions & 264 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}

libraries/rush-lib/src/api/test/__snapshots__/RushCommandLine.test.ts.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,18 +1149,18 @@ Object {
11491149
"shortName": undefined,
11501150
},
11511151
Object {
1152-
"description": "A list of Rush project names that will be hotlinked to the \\"--path\\" folder. If not specified, the default is the project of the current working directory.",
1152+
"description": "Specify which installed versions should be hotlinked.",
11531153
"environmentVariable": undefined,
1154-
"kind": "StringList",
1155-
"longName": "--project",
1154+
"kind": "String",
1155+
"longName": "--version",
11561156
"required": false,
11571157
"shortName": undefined,
11581158
},
11591159
Object {
1160-
"description": "Specify which installed versions should be hotlinked. If omitted, the default is all versions (\\"*).",
1160+
"description": "The name of the subspace to use for the hotlinked package.",
11611161
"environmentVariable": undefined,
1162-
"kind": "String",
1163-
"longName": "--version",
1162+
"kind": "StringList",
1163+
"longName": "--subspace",
11641164
"required": false,
11651165
"shortName": undefined,
11661166
},
Lines changed: 4 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4-
import type {
5-
CommandLineStringListParameter,
6-
IRequiredCommandLineStringParameter
7-
} from '@rushstack/ts-command-line';
4+
import type { IRequiredCommandLineStringParameter } from '@rushstack/ts-command-line';
85
import path from 'path';
9-
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
6+
107
import { HotlinkManager } from '../../utilities/HotlinkManager';
118
import { BaseRushAction, type IBaseRushActionOptions } from './BaseRushAction';
12-
import { Async } from '@rushstack/node-core-library';
13-
import { RushConstants } from '../../logic/RushConstants';
149

1510
export abstract class BaseHotlinkPackageAction extends BaseRushAction {
16-
protected readonly _projectList: CommandLineStringListParameter;
1711
protected readonly _pathParameter: IRequiredCommandLineStringParameter;
1812

1913
protected constructor(options: IBaseRushActionOptions) {
@@ -27,59 +21,16 @@ export abstract class BaseHotlinkPackageAction extends BaseRushAction {
2721
'The path of folder of a project outside of this Rush repo, whose installation will be simulated using' +
2822
' node_modules symlinks ("hotlinks"). This folder is the symlink target.'
2923
});
30-
31-
this._projectList = this.defineStringListParameter({
32-
parameterLongName: '--project',
33-
required: false,
34-
argumentName: 'PROJECT',
35-
description:
36-
'A list of Rush project names that will be hotlinked to the "--path" folder. ' +
37-
'If not specified, the default is the project of the current working directory.'
38-
});
3924
}
4025

41-
protected abstract connectPackageAsync(
42-
consumerPackage: RushConfigurationProject,
26+
protected abstract hotlinkPackageAsync(
4327
linkedPackagePath: string,
4428
hotlinkManager: HotlinkManager
4529
): Promise<void>;
4630

47-
protected async getProjectsToLinkAsync(): Promise<Set<RushConfigurationProject>> {
48-
const projectsToLink: Set<RushConfigurationProject> = new Set();
49-
const projectNames: readonly string[] = this._projectList.values;
50-
51-
if (projectNames.length > 0) {
52-
for (const projectName of projectNames) {
53-
const project: RushConfigurationProject | undefined =
54-
this.rushConfiguration.getProjectByName(projectName);
55-
if (!project) {
56-
throw new Error(`The project "${projectName}" was not found in "${RushConstants.rushPackageName}"`);
57-
}
58-
projectsToLink.add(project);
59-
}
60-
} else {
61-
const currentProject: RushConfigurationProject | undefined =
62-
this.rushConfiguration.tryGetProjectForPath(process.cwd());
63-
if (!currentProject) {
64-
throw new Error(`No Rush project was found in the current working directory`);
65-
}
66-
projectsToLink.add(currentProject);
67-
}
68-
69-
return projectsToLink;
70-
}
71-
7231
protected async runAsync(): Promise<void> {
7332
const hotlinkManager: HotlinkManager = HotlinkManager.loadFromRushConfiguration(this.rushConfiguration);
7433
const linkedPackagePath: string = path.resolve(process.cwd(), this._pathParameter.value);
75-
const projectsToLink: Set<RushConfigurationProject> = await this.getProjectsToLinkAsync();
76-
77-
await Async.forEachAsync(
78-
projectsToLink,
79-
async (project) => {
80-
await this.connectPackageAsync(project, linkedPackagePath, hotlinkManager);
81-
},
82-
{ concurrency: 5 }
83-
);
34+
await this.hotlinkPackageAsync(linkedPackagePath, hotlinkManager);
8435
}
8536
}
Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4-
import type { CommandLineStringParameter } from '@rushstack/ts-command-line';
4+
import type {
5+
CommandLineStringListParameter,
6+
IRequiredCommandLineStringParameter
7+
} from '@rushstack/ts-command-line';
58

69
import type { RushCommandLineParser } from '../RushCommandLineParser';
7-
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
810
import { BaseHotlinkPackageAction } from './BaseHotlinkPackageAction';
911
import type { HotlinkManager } from '../../utilities/HotlinkManager';
1012
import { BRIDGE_PACKAGE_ACTION_NAME, LINK_PACKAGE_ACTION_NAME } from '../../utilities/actionNameConstants';
13+
import { RushConstants } from '../../logic/RushConstants';
14+
import type { Subspace } from '../../api/Subspace';
15+
import { Async } from '@rushstack/node-core-library';
16+
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
1117

1218
export class BridgePackageAction extends BaseHotlinkPackageAction {
13-
private readonly _version: CommandLineStringParameter;
19+
private readonly _versionParameter: IRequiredCommandLineStringParameter;
20+
private readonly _subspaceNamesParameter: CommandLineStringListParameter;
1421

1522
public constructor(parser: RushCommandLineParser) {
1623
super({
@@ -28,20 +35,58 @@ export class BridgePackageAction extends BaseHotlinkPackageAction {
2835
parser
2936
});
3037

31-
this._version = this.defineStringParameter({
38+
this._versionParameter = this.defineStringParameter({
3239
parameterLongName: '--version',
3340
argumentName: 'SEMVER_RANGE',
34-
description:
35-
'Specify which installed versions should be hotlinked. If omitted, the default is all versions ("*).'
41+
defaultValue: '*',
42+
description: 'Specify which installed versions should be hotlinked.'
43+
});
44+
45+
this._subspaceNamesParameter = this.defineStringListParameter({
46+
parameterLongName: '--subspace',
47+
argumentName: 'SUBSPACE_NAME',
48+
description: 'The name of the subspace to use for the hotlinked package.'
3649
});
3750
}
3851

39-
public async connectPackageAsync(
40-
consumerPackage: RushConfigurationProject,
52+
private _getSubspacesToBridgeAsync(): Set<Subspace> {
53+
const subspaceToBridge: Set<Subspace> = new Set();
54+
const subspaceNames: readonly string[] = this._subspaceNamesParameter.values;
55+
56+
if (subspaceNames.length > 0) {
57+
for (const subspaceName of subspaceNames) {
58+
const subspace: Subspace | undefined = this.rushConfiguration.tryGetSubspace(subspaceName);
59+
if (!subspace) {
60+
throw new Error(
61+
`The subspace "${subspaceName}" was not found in "${RushConstants.rushPackageName}"`
62+
);
63+
}
64+
subspaceToBridge.add(subspace);
65+
}
66+
} else {
67+
const currentProject: RushConfigurationProject | undefined =
68+
this.rushConfiguration.tryGetProjectForPath(process.cwd());
69+
if (!currentProject) {
70+
throw new Error(`No Rush project was found in the current working directory`);
71+
}
72+
subspaceToBridge.add(currentProject.subspace);
73+
}
74+
75+
return subspaceToBridge;
76+
}
77+
78+
protected async hotlinkPackageAsync(
4179
linkedPackagePath: string,
4280
hotlinkManager: HotlinkManager
4381
): Promise<void> {
44-
const version: string | undefined = this._version.value;
45-
await hotlinkManager.bridgePackageAsync(this.terminal, consumerPackage, linkedPackagePath, version);
82+
const version: string = this._versionParameter.value;
83+
const subspaces: Set<Subspace> = await this._getSubspacesToBridgeAsync();
84+
await Async.forEachAsync(
85+
subspaces,
86+
async (subspace) => {
87+
await hotlinkManager.bridgePackageAsync(this.terminal, subspace, linkedPackagePath, version);
88+
},
89+
{ concurrency: 5 }
90+
);
4691
}
4792
}

libraries/rush-lib/src/cli/actions/LinkPackageAction.ts

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4+
import { Async } from '@rushstack/node-core-library';
5+
import type { CommandLineStringListParameter } from '@rushstack/ts-command-line';
6+
47
import type { RushCommandLineParser } from '../RushCommandLineParser';
58
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
69
import { BaseHotlinkPackageAction } from './BaseHotlinkPackageAction';
710
import type { HotlinkManager } from '../../utilities/HotlinkManager';
811
import { BRIDGE_PACKAGE_ACTION_NAME, LINK_PACKAGE_ACTION_NAME } from '../../utilities/actionNameConstants';
12+
import { RushConstants } from '../../logic/RushConstants';
913

1014
export class LinkPackageAction extends BaseHotlinkPackageAction {
15+
protected readonly _projectListParameter: CommandLineStringListParameter;
16+
1117
public constructor(parser: RushCommandLineParser) {
1218
super({
1319
actionName: LINK_PACKAGE_ACTION_NAME,
@@ -24,13 +30,53 @@ export class LinkPackageAction extends BaseHotlinkPackageAction {
2430
' including indirect dependencies.',
2531
parser
2632
});
33+
34+
this._projectListParameter = this.defineStringListParameter({
35+
parameterLongName: '--project',
36+
argumentName: 'PROJECT_NAME',
37+
required: false,
38+
description:
39+
'A list of Rush project names that will be hotlinked to the "--path" folder. ' +
40+
'If not specified, the default is the project of the current working directory.'
41+
});
42+
}
43+
44+
private async _getProjectsToLinkAsync(): Promise<Set<RushConfigurationProject>> {
45+
const projectsToLink: Set<RushConfigurationProject> = new Set();
46+
const projectNames: readonly string[] = this._projectListParameter.values;
47+
48+
if (projectNames.length > 0) {
49+
for (const projectName of projectNames) {
50+
const project: RushConfigurationProject | undefined =
51+
this.rushConfiguration.getProjectByName(projectName);
52+
if (!project) {
53+
throw new Error(`The project "${projectName}" was not found in "${RushConstants.rushPackageName}"`);
54+
}
55+
projectsToLink.add(project);
56+
}
57+
} else {
58+
const currentProject: RushConfigurationProject | undefined =
59+
this.rushConfiguration.tryGetProjectForPath(process.cwd());
60+
if (!currentProject) {
61+
throw new Error(`No Rush project was found in the current working directory`);
62+
}
63+
projectsToLink.add(currentProject);
64+
}
65+
66+
return projectsToLink;
2767
}
2868

29-
public async connectPackageAsync(
30-
consumerPackage: RushConfigurationProject,
69+
protected async hotlinkPackageAsync(
3170
linkedPackagePath: string,
3271
hotlinkManager: HotlinkManager
3372
): Promise<void> {
34-
await hotlinkManager.linkPackageAsync(this.terminal, consumerPackage, linkedPackagePath);
73+
const projectsToLink: Set<RushConfigurationProject> = await this._getProjectsToLinkAsync();
74+
await Async.forEachAsync(
75+
projectsToLink,
76+
async (project) => {
77+
await hotlinkManager.linkPackageAsync(this.terminal, project, linkedPackagePath);
78+
},
79+
{ concurrency: 5 }
80+
);
3581
}
3682
}

libraries/rush-lib/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ Optional arguments:
155155
`;
156156
157157
exports[`CommandLineHelp prints the help for each action: bridge-package 1`] = `
158-
"usage: rush bridge-package [-h] --path PATH [--project PROJECT]
159-
[--version SEMVER_RANGE]
158+
"usage: rush bridge-package [-h] --path PATH [--version SEMVER_RANGE]
159+
[--subspace SUBSPACE_NAME]
160160
161161
162162
This command enables you to test a locally built project by simulating its
@@ -175,12 +175,12 @@ Optional arguments:
175175
repo, whose installation will be simulated using
176176
node_modules symlinks (\\"hotlinks\\"). This folder is
177177
the symlink target.
178-
--project PROJECT A list of Rush project names that will be hotlinked
179-
to the \\"--path\\" folder. If not specified, the default
180-
is the project of the current working directory.
181178
--version SEMVER_RANGE
182179
Specify which installed versions should be hotlinked.
183-
If omitted, the default is all versions (\\"*).
180+
The default value is \\"*\\".
181+
--subspace SUBSPACE_NAME
182+
The name of the subspace to use for the hotlinked
183+
package.
184184
"
185185
`;
186186
@@ -877,7 +877,7 @@ Optional arguments:
877877
`;
878878
879879
exports[`CommandLineHelp prints the help for each action: link-package 1`] = `
880-
"usage: rush link-package [-h] --path PATH [--project PROJECT]
880+
"usage: rush link-package [-h] --path PATH [--project PROJECT_NAME]
881881
882882
This command enables you to test a locally built project by creating a
883883
symlink under the specified projects' node_modules folders. The
@@ -890,14 +890,15 @@ bridge-package\\" command, which affects the entire lockfile including indirect
890890
dependencies.
891891
892892
Optional arguments:
893-
-h, --help Show this help message and exit.
894-
--path PATH The path of folder of a project outside of this Rush
895-
repo, whose installation will be simulated using
896-
node_modules symlinks (\\"hotlinks\\"). This folder is the
897-
symlink target.
898-
--project PROJECT A list of Rush project names that will be hotlinked to
899-
the \\"--path\\" folder. If not specified, the default is
900-
the project of the current working directory.
893+
-h, --help Show this help message and exit.
894+
--path PATH The path of folder of a project outside of this Rush
895+
repo, whose installation will be simulated using
896+
node_modules symlinks (\\"hotlinks\\"). This folder is
897+
the symlink target.
898+
--project PROJECT_NAME
899+
A list of Rush project names that will be hotlinked
900+
to the \\"--path\\" folder. If not specified, the default
901+
is the project of the current working directory.
901902
"
902903
`;
903904

libraries/rush-lib/src/schemas/rush-hotlink-state.schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
"type": "string"
3737
},
3838

39+
"affectedPnpmVirtualStoreFolderPaths": {
40+
"type": "array",
41+
"items": {
42+
"type": "string"
43+
}
44+
},
45+
3946
"linkType": {
4047
"type": "string",
4148
"enum": ["LinkPackage", "BridgePackage"]

0 commit comments

Comments
 (0)