Skip to content

Commit fb0cdcd

Browse files
authored
Merge pull request microsoft#1769 from iclanton/ianc/prepare-to-publish-rush
[rush] Prepare to publish Rush 5.21.0
2 parents 4575f1c + ac72b09 commit fb0cdcd

File tree

10 files changed

+87
-151
lines changed

10 files changed

+87
-151
lines changed

apps/rush-lib/assets/rush-init/rush.json

+14-12
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@
3636
*/
3737
"pnpmOptions": {
3838
/**
39-
* Specifies the location of the PNPM store. There are three possible values:
40-
*
41-
* - "local" - use the "pnpm-store" folder in the current configured temp folder:
42-
* "common/temp/pnpm-store" by default.
43-
* - "global" - use PNPM's global store, which has the benefit of being shared
44-
* across multiple repo folders, but the disadvantage of less isolation for builds
45-
* (e.g. bugs or incompatibilities when two repos use different releases of PNPM)
46-
*
47-
* RUSH_PNPM_STORE_PATH will override the directory that will be used as the store
48-
*
49-
* The default value is "local".
50-
*/
39+
* Specifies the location of the PNPM store. There are two possible values:
40+
*
41+
* - "local" - use the "pnpm-store" folder in the current configured temp folder:
42+
* "common/temp/pnpm-store" by default.
43+
* - "global" - use PNPM's global store, which has the benefit of being shared
44+
* across multiple repo folders, but the disadvantage of less isolation for builds
45+
* (e.g. bugs or incompatibilities when two repos use different releases of PNPM)
46+
*
47+
* RUSH_PNPM_STORE_PATH will override the directory that will be used as the store
48+
*
49+
* In all cases, the store path will be overridden by the environment variable RUSH_PNPM_STORE_PATH.
50+
*
51+
* The default value is "local".
52+
*/
5153
/*[LINE "HYPOTHETICAL"]*/ "pnpmStore": "local",
5254

5355
/**

apps/rush-lib/src/api/EnvironmentConfiguration.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,11 @@ export const enum EnvironmentVariableNames {
4949
RUSH_ABSOLUTE_SYMLINKS = 'RUSH_ABSOLUTE_SYMLINKS',
5050

5151
/**
52-
* When using PNPM as the package manager this variable will be used to define the path that
52+
* When using PNPM as the package manager, this variable can be used to configure the path that
5353
* PNPM will use as the store directory.
54-
*
54+
*
5555
* If a relative path is used, then the store path will be resolved relative to the process's
56-
* current working directory. The best way to use this environment variable is with absolute
57-
* paths.
56+
* current working directory. An absolute path is recommended.
5857
*/
5958
RUSH_PNPM_STORE_PATH = 'RUSH_PNPM_STORE_PATH'
6059
}

apps/rush-lib/src/api/LastInstallFlag.ts

+44-84
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,9 @@ import { PackageManagerName } from './packageManager/PackageManager'
66

77
export const LAST_INSTALL_FLAG_FILE_NAME: string = 'last-install.flag';
88

9-
interface ILastInstallFlagErrorState {
10-
oldState: JsonObject;
11-
newState: JsonObject;
12-
}
13-
14-
/**
15-
* Defines an `Error` of type `LastInstallFlagError` that can be generated by `LastInstallFlag`
16-
* when it is needed.
17-
* @internal
18-
*/
19-
export class LastInstallFlagError extends Error {
20-
/**
21-
* Creates a new LastInstallFlagError
22-
* @param errorKey - The error to generate
23-
* @param state - Object containing the old and new LastInstallFlag state
24-
*/
25-
public constructor(errorKey: string, state: ILastInstallFlagErrorState) {
26-
super();
27-
28-
const { oldState, newState } = state;
29-
30-
switch (errorKey) {
31-
case 'storePath': {
32-
const oldStorePath: string = oldState.storePath || '<global>';
33-
const newStorePath: string = newState.storePath || '<global>';
34-
this.message =
35-
"Current PNPM store path does not match the last one used. This may cause inconsistency in your builds.\n\n" +
36-
"If you wish to install with the new store path, please run \"rush update --purge\"\n\n" +
37-
`Old Path: ${oldStorePath}\n` +
38-
`New Path: ${newStorePath}`
39-
break;
40-
}
41-
default: {
42-
// the `errorKey` didn't have an error key defined. Throw an Error
43-
// so the developer knows.
44-
throw new Error(`LastInstallFlagError: an invalid 'errorKey' was defined\nThe key '${errorKey}' does not have an error message defined`);
45-
break;
46-
}
47-
}
48-
}
49-
50-
51-
}
52-
539
/**
5410
* A helper class for managing last-install flags, which are persistent and
55-
* indicate that something installed in the folder was sucessfully completed.
11+
* indicate that something installed in the folder was successfully completed.
5612
* It also compares state, so that if something like the Node.js version has changed,
5713
* it can invalidate the last install.
5814
* @internal
@@ -72,57 +28,61 @@ export class LastInstallFlag {
7228
}
7329

7430
/**
75-
* Returns true if the file exists and the contents match the current state
76-
* @param abortOnInvalid - If the current state is not equal to the previous
77-
* state, and an the current state causes an error, then throw an exception
78-
* with a friendly message
31+
* Returns true if the file exists and the contents match the current state.
32+
*/
33+
public isValid(): boolean {
34+
return this._isValid(false);
35+
}
36+
37+
/**
38+
* Same as isValid(), but with an additional check: If the current state is not equal to the previous
39+
* state, and an the current state causes an error, then throw an exception with a friendly message.
7940
*/
80-
public isValid(abortOnInvalid: boolean = false): boolean {
41+
public checkValidAndReportStoreIssues(): boolean {
42+
return this._isValid(true);
43+
}
44+
45+
private _isValid(checkValidAndReportStoreIssues: boolean): boolean {
8146
if (!FileSystem.exists(this._path)) {
8247
return false;
8348
}
84-
let contents: JsonObject;
49+
50+
let oldState: JsonObject;
8551
try {
86-
contents = JsonFile.load(this._path);
52+
oldState = JsonFile.load(this._path);
8753
} catch (err) {
8854
return false;
89-
}
90-
if (!_.isEqual(contents, this._state)) {
91-
if (abortOnInvalid) {
92-
const flagError: LastInstallFlagError | void = this._stateHasError(contents);
93-
if (flagError) {
94-
throw flagError;
95-
}
96-
}
97-
return false;
9855
}
99-
return true;
100-
}
10156

102-
/**
103-
* Determine if the new LastInstallFlag state should generate an error
104-
* @param oldState - The LastInstallFlag contents read from the disk
105-
*/
106-
private _stateHasError(oldState: JsonObject): LastInstallFlagError | void {
107-
const pkgManager: PackageManagerName = this._state.packageManager;
108-
switch (pkgManager) {
109-
case 'pnpm': {
110-
if (
111-
( // Only throw an error if the package manager hasn't changed from pnpm
112-
oldState.packageManager === pkgManager
113-
) && ( // Throw if the store path changed
114-
oldState.storePath &&
115-
oldState.storePath !== this._state.storePath
116-
)
117-
) {
118-
return new LastInstallFlagError('storePath', {
119-
newState: this._state,
120-
oldState,
121-
});
57+
const newState: JsonObject = this._state;
58+
59+
if (!_.isEqual(oldState, newState)) {
60+
if (checkValidAndReportStoreIssues) {
61+
const pkgManager: PackageManagerName = newState.packageManager;
62+
if (pkgManager === 'pnpm') {
63+
if (
64+
( // Only throw an error if the package manager hasn't changed from PNPM
65+
oldState.packageManager === pkgManager
66+
) && ( // Throw if the store path changed
67+
oldState.storePath &&
68+
oldState.storePath !== newState.storePath
69+
)
70+
) {
71+
const oldStorePath: string = oldState.storePath || '<global>';
72+
const newStorePath: string = newState.storePath || '<global>';
73+
74+
throw new Error("Current PNPM store path does not match the last one used." +
75+
" This may cause inconsistency in your builds.\n\n" +
76+
"If you wish to install with the new store path, please run \"rush update --purge\"\n\n" +
77+
`Old Path: ${oldStorePath}\n` +
78+
`New Path: ${newStorePath}`);
79+
}
12280
}
123-
break;
12481
}
82+
return false;
12583
}
84+
85+
return true;
12686
}
12787

12888
/**

apps/rush-lib/src/api/RushConfiguration.ts

+6-23
Original file line numberDiff line numberDiff line change
@@ -124,21 +124,6 @@ export interface IPnpmOptionsJson {
124124
resolutionStrategy?: ResolutionStrategy;
125125
}
126126

127-
/**
128-
* The paths used when resolving `pnpmStorePath`
129-
* @internal
130-
*/
131-
export interface IPnpmOptionsRootPaths {
132-
/**
133-
* The location of the Rush `common/temp` directory
134-
*/
135-
commonTempFolder: string;
136-
/**
137-
* Stores the location of the repository root
138-
*/
139-
repoRoot: string;
140-
}
141-
142127
/**
143128
* Part of IRushConfigurationJson.
144129
*/
@@ -209,7 +194,7 @@ export interface ICurrentVariantJson {
209194
export class PnpmOptionsConfiguration {
210195
/**
211196
* The method used to resolve the store used by PNPM.
212-
*
197+
*
213198
* @remarks
214199
* Available options:
215200
* - local: Use the standard Rush store path: common/temp/pnpm-store
@@ -219,7 +204,7 @@ export class PnpmOptionsConfiguration {
219204

220205
/**
221206
* The path for PNPM to use as the store directory.
222-
*
207+
*
223208
* Will be overridden by environment variable RUSH_PNPM_STORE_PATH
224209
*/
225210
public readonly pnpmStorePath: string;
@@ -254,14 +239,14 @@ export class PnpmOptionsConfiguration {
254239
public readonly resolutionStrategy: ResolutionStrategy;
255240

256241
/** @internal */
257-
public constructor(json: IPnpmOptionsJson, rootPaths: IPnpmOptionsRootPaths) {
242+
public constructor(json: IPnpmOptionsJson, commonTempFolder: string) {
258243
this.pnpmStore = json.pnpmStore || 'local';
259244
if (EnvironmentConfiguration.pnpmStorePathOverride) {
260245
this.pnpmStorePath = EnvironmentConfiguration.pnpmStorePathOverride;
261246
} else if (this.pnpmStore === 'global') {
262247
this.pnpmStorePath = '';
263248
} else {
264-
this.pnpmStorePath = path.resolve(path.join(rootPaths.commonTempFolder, 'pnpm-store'));
249+
this.pnpmStorePath = path.resolve(path.join(commonTempFolder, 'pnpm-store'));
265250
}
266251
this.strictPeerDependencies = !!json.strictPeerDependencies;
267252
this.resolutionStrategy = json.resolutionStrategy || 'fewer-dependencies';
@@ -435,10 +420,8 @@ export class RushConfiguration {
435420
);
436421
this._experimentsConfiguration = new ExperimentsConfiguration(experimentsConfigFile);
437422

438-
this._pnpmOptions = new PnpmOptionsConfiguration(rushConfigurationJson.pnpmOptions || {}, {
439-
commonTempFolder: this._commonTempFolder,
440-
repoRoot: this._rushJsonFolder
441-
});
423+
this._pnpmOptions = new PnpmOptionsConfiguration(rushConfigurationJson.pnpmOptions || {},
424+
this._commonTempFolder);
442425
this._yarnOptions = new YarnOptionsConfiguration(rushConfigurationJson.yarnOptions || {});
443426

444427
// TODO: Add an actual "packageManager" field in rush.json

apps/rush-lib/src/api/test/LastInstallFlag.test.ts

+4-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as path from 'path';
22

3-
import { LastInstallFlag, LastInstallFlagError } from '../LastInstallFlag';
3+
import { LastInstallFlag } from '../LastInstallFlag';
44
import { FileSystem } from '@microsoft/node-core-library';
55

66
const TEMP_DIR: string = path.join(__dirname, 'temp');
@@ -79,11 +79,7 @@ describe('LastInstallFlag', () => {
7979
});
8080

8181
flag1.create();
82-
expect(() => { flag2.isValid(true) }).toThrowError(
83-
// @ts-ignore
84-
LastInstallFlagError // Constructor is private
85-
);
86-
expect(() => { flag2.isValid(true) }).toThrowError(/PNPM store path/);
82+
expect(() => { flag2.checkValidAndReportStoreIssues() }).toThrowError(/PNPM store path/);
8783
});
8884

8985
it('doesn\'t throw an error if conditions for error aren\'t met', () => {
@@ -96,16 +92,7 @@ describe('LastInstallFlag', () => {
9692
});
9793

9894
flag1.create();
99-
expect(() => { flag2.isValid(true) }).not.toThrow();
100-
expect(flag2.isValid(true)).toEqual(false);
95+
expect(() => { flag2.checkValidAndReportStoreIssues() }).not.toThrow();
96+
expect(flag2.checkValidAndReportStoreIssues()).toEqual(false);
10197
})
10298
});
103-
104-
describe('LastInstallFlagError', () => {
105-
it('throws an Error if an invalid error key is defined', () => {
106-
expect(() => {
107-
// @ts-ignore
108-
const flagError: LastInstallFlagError = new LastInstallFlagError('non-existant key'); // eslint-disable-line @typescript-eslint/no-unused-vars
109-
}).toThrowError();
110-
})
111-
});

apps/rush-lib/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export {
1717
PnpmOptionsConfiguration,
1818
IPnpmOptionsJson as _IPnpmOptionsJson,
1919
PnpmStoreOptions,
20-
IPnpmOptionsRootPaths as _IPnpmOptionsRootPaths,
2120
YarnOptionsConfiguration
2221
} from './api/RushConfiguration';
2322

apps/rush-lib/src/logic/InstallManager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ export class InstallManager {
820820
'node_modules');
821821

822822
// This marker file indicates that the last "rush install" completed successfully
823-
const markerFileExistedAndWasValidAtStart: boolean = this._commonNodeModulesMarker.isValid(true);
823+
const markerFileExistedAndWasValidAtStart: boolean = this._commonNodeModulesMarker.checkValidAndReportStoreIssues();
824824

825825
// If "--clean" or "--full-clean" was specified, or if the last install was interrupted,
826826
// then we will need to delete the node_modules folder. Otherwise, we can do an incremental

apps/rush-lib/src/schemas/rush.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"type": "object",
5959
"properties": {
6060
"pnpmStore": {
61-
"description": "Specifies the location of the PNPM store. There are two possible values:\n\n\"local\" - uuse the \"pnpm-store\" folder in the current configured temp folder: \"common/temp/pnpm-store\" by default.\n\"global\" - use PNPM's global store, which has the benefit of being shared across multiple repo folders, but the disadvantage of less isolation for builds (e.g. bugs or incompatibilities when two repos use different releases of PNPM)\n\nThe default value is \"local\".\n\nIn all cases, the store path will be overridden by the environment variable RUSH_PNPM_STORE_PATH",
61+
"description": "Specifies the location of the PNPM store. There are two possible values:\n\n\"local\" - use the \"pnpm-store\" folder in the current configured temp folder: \"common/temp/pnpm-store\" by default.\n\"global\" - use PNPM's global store, which has the benefit of being shared across multiple repo folders, but the disadvantage of less isolation for builds (e.g. bugs or incompatibilities when two repos use different releases of PNPM)\n\nIn all cases, the store path will be overridden by the environment variable RUSH_PNPM_STORE_PATH.\n\nThe default value is \"local\".",
6262
"type": "string",
6363
"enum": ["local", "global"]
6464
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush",
10+
"email": "[email protected]"
11+
}

common/reviews/api/rush-lib.api.md

+3-8
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,6 @@ export interface _IPnpmOptionsJson {
152152
strictPeerDependencies?: boolean;
153153
}
154154

155-
// @internal
156-
export interface _IPnpmOptionsRootPaths {
157-
commonTempFolder: string;
158-
repoRoot: string;
159-
}
160-
161155
// @public
162156
export interface ITryFindRushJsonLocationOptions {
163157
showVerbose?: boolean;
@@ -167,9 +161,10 @@ export interface ITryFindRushJsonLocationOptions {
167161
// @internal
168162
export class _LastInstallFlag {
169163
constructor(folderPath: string, state?: JsonObject);
164+
checkValidAndReportStoreIssues(): boolean;
170165
clear(): void;
171166
create(): void;
172-
isValid(abortOnInvalid?: boolean): boolean;
167+
isValid(): boolean;
173168
readonly path: string;
174169
}
175170

@@ -244,7 +239,7 @@ export type PackageManagerName = 'pnpm' | 'npm' | 'yarn';
244239
// @public
245240
export class PnpmOptionsConfiguration {
246241
// @internal
247-
constructor(json: _IPnpmOptionsJson, rootPaths: _IPnpmOptionsRootPaths);
242+
constructor(json: _IPnpmOptionsJson, commonTempFolder: string);
248243
readonly pnpmStore: PnpmStoreOptions;
249244
readonly pnpmStorePath: string;
250245
readonly resolutionStrategy: ResolutionStrategy;

0 commit comments

Comments
 (0)