Skip to content

Commit 80f2d64

Browse files
committed
Merge branch 'feat/pkg-mngr-impl' into refactor/pkg-mgr-replace
2 parents 666c4d8 + 6e28e94 commit 80f2d64

File tree

4 files changed

+28
-105
lines changed

4 files changed

+28
-105
lines changed

lib/base-package-manager.ts

+12-60
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,26 @@
1-
import * as child_process from 'child_process';
1+
import { isInteractive } from "./common/helpers";
22

33
export class BasePackageManager {
4-
constructor(private packageManager: string) { }
4+
constructor(
5+
protected $childProcess: IChildProcess,
6+
private $hostInfo: IHostInfo,
7+
private packageManager: string
8+
) { }
59

6-
protected getNpmExecutableName(isWindows: boolean): string {
10+
protected getPackageManagerExecutableName(): string {
711
let npmExecutableName = this.packageManager;
812

9-
if (isWindows) {
13+
if (this.$hostInfo.isWindows) {
1014
npmExecutableName += ".cmd";
1115
}
1216

1317
return npmExecutableName;
1418
}
1519

16-
protected async processPackageManagerInstall(
17-
childProcess: child_process.ChildProcess,
18-
isWindows: boolean,
19-
params: string[],
20-
): Promise<ISpawnResult> {
21-
return new Promise<ISpawnResult>((resolve, reject) => {
22-
let isFulfilled = false;
23-
let capturedOut = "";
24-
let capturedErr = "";
25-
26-
const npmExecutable = this.getNpmExecutableName(isWindows);
27-
28-
if (childProcess.stdout) {
29-
childProcess.stdout.on("data", (data: string) => {
30-
capturedOut += data;
31-
});
32-
}
33-
34-
if (childProcess.stderr) {
35-
childProcess.stderr.on("data", (data: string) => {
36-
capturedErr += data;
37-
});
38-
}
39-
40-
childProcess.on("close", (arg: any) => {
41-
const exitCode = typeof arg === "number" ? arg : arg && arg.code;
42-
43-
if (exitCode === 0) {
44-
isFulfilled = true;
45-
const result = {
46-
stdout: capturedOut,
47-
stderr: capturedErr,
48-
exitCode
49-
};
50-
51-
resolve(result);
52-
} else {
53-
let errorMessage = `Command ${npmExecutable} ${params && params.join(" ")} failed with exit code ${exitCode}`;
54-
if (capturedErr) {
55-
errorMessage += ` Error output: \n ${capturedErr}`;
56-
}
57-
58-
if (!isFulfilled) {
59-
isFulfilled = true;
60-
reject(new Error(errorMessage));
61-
}
62-
}
63-
});
64-
65-
childProcess.on("error", (err: Error) => {
66-
if (!isFulfilled) {
67-
isFulfilled = true;
68-
reject(err);
69-
}
70-
});
71-
});
20+
protected async processPackageManagerInstall(params: string[], opts: { cwd: string }) {
21+
const npmExecutable = this.getPackageManagerExecutableName();
22+
const stdioValue = isInteractive() ? "inherit" : "pipe";
23+
return await this.$childProcess.spawnFromEvent(npmExecutable, params, "close", { cwd: opts.cwd, stdio: stdioValue });
7224
}
7325

7426
protected getFlagsString(config: any, asArray: boolean): any {

lib/node-package-manager.ts

+7-22
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import * as path from "path";
22
import { BasePackageManager } from "./base-package-manager";
33
import { exported, cache } from "./common/decorators";
4-
import { isInteractive } from "./common/helpers";
54
import { CACACHE_DIRECTORY_NAME } from "./constants";
65

76
export class NodePackageManager extends BasePackageManager implements INodePackageManager {
87
private static SCOPED_DEPENDENCY_REGEXP = /^(@.+?)(?:@(.+?))?$/;
98
private static DEPENDENCY_REGEXP = /^(.+?)(?:@(.+?))?$/;
109

11-
constructor(private $fs: IFileSystem,
12-
private $hostInfo: IHostInfo,
10+
constructor(
11+
$childProcess: IChildProcess,
1312
private $errors: IErrors,
14-
private $childProcess: IChildProcess,
13+
private $fs: IFileSystem,
14+
$hostInfo: IHostInfo,
1515
private $logger: ILogger,
1616
private $httpClient: Server.IHttpClient) {
17-
super('npm');
17+
super($childProcess, $hostInfo, 'npm');
1818
}
1919

2020
@exported("npm")
@@ -56,7 +56,7 @@ export class NodePackageManager extends BasePackageManager implements INodePacka
5656
}
5757

5858
try {
59-
const spawnResult: ISpawnResult = await this.getNpmInstallResult(params, cwd);
59+
const spawnResult: ISpawnResult = await this.processPackageManagerInstall(params, { cwd });
6060

6161
// Whenever calling npm install without any arguments (hence installing all dependencies) no output is emitted on stdout
6262
// Luckily, whenever you call npm install to install all dependencies chances are you won't need the name/version of the package you're installing because there is none.
@@ -69,7 +69,7 @@ export class NodePackageManager extends BasePackageManager implements INodePacka
6969
// We cannot use the actual install with --json to get the information because of post-install scripts which may print on stdout
7070
// dry-run install is quite fast when the dependencies are already installed even for many dependencies (e.g. angular) so we can live with this approach
7171
// We need the --prefix here because without it no output is emitted on stdout because all the dependencies are already installed.
72-
const spawnNpmDryRunResult = await this.$childProcess.spawnFromEvent(this.getNpmExecutableName(this.$hostInfo.isWindows), params, "close");
72+
const spawnNpmDryRunResult = await this.$childProcess.spawnFromEvent(this.getPackageManagerExecutableName(), params, "close");
7373
return this.parseNpmInstallResult(spawnNpmDryRunResult.stdout, spawnResult.stdout, packageName);
7474
} catch (err) {
7575
if (err.message && err.message.indexOf("EPEERINVALID") !== -1) {
@@ -211,21 +211,6 @@ export class NodePackageManager extends BasePackageManager implements INodePacka
211211
version
212212
};
213213
}
214-
215-
private async getNpmInstallResult(params: string[], cwd: string): Promise<ISpawnResult> {
216-
return new Promise<ISpawnResult>(async (resolve, reject) => {
217-
const npmExecutable = this.getNpmExecutableName(this.$hostInfo.isWindows);
218-
const stdioValue = isInteractive() ? "inherit" : "pipe";
219-
const childProcess = this.$childProcess.spawn(npmExecutable, params, { cwd, stdio: stdioValue });
220-
221-
try {
222-
const result = await this.processPackageManagerInstall(childProcess, this.$hostInfo.isWindows, params);
223-
resolve(result);
224-
} catch (e) {
225-
reject(e);
226-
}
227-
});
228-
}
229214
}
230215

231216
$injector.register("npm", NodePackageManager);

lib/package-manager.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ export class PackageManager implements INodePackageManager {
3939
}
4040

4141
private _determinePackageManager(): void {
42-
this.$userSettingsService.getSettingValue('packageManager').then ( (pm: string) => {
42+
this.$userSettingsService.getSettingValue('packageManager')
43+
.then((pm: string) => {
4344
if (pm === 'yarn' || this.$options.yarn) {
4445
this.packageManager = this.$yarn;
4546
} else {
4647
this.packageManager = this.$npm;
4748
}
48-
}, (err) => {
49+
})
50+
.catch((err) => {
4951
this.$errors.fail(`Unable to read package manager config from user settings ${err}`);
5052
});
5153
}

lib/yarn-package-manager.ts

+5-21
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
import * as path from "path";
22
import { BasePackageManager } from "./base-package-manager";
33
import { exported } from './common/decorators';
4-
import { isInteractive } from "./common/helpers";
54

65
export class YarnPackageManager extends BasePackageManager implements INodePackageManager {
76

87
constructor(
9-
private $childProcess: IChildProcess,
8+
$childProcess: IChildProcess,
109
private $errors: IErrors,
1110
private $fs: IFileSystem,
12-
private $hostInfo: IHostInfo,
11+
$hostInfo: IHostInfo,
1312
private $httpClient: Server.IHttpClient,
1413
private $logger: ILogger,
1514
private $pacoteService: IPacoteService
1615
) {
17-
super('yarn');
16+
super($childProcess, $hostInfo, 'yarn');
1817
}
1918

2019
@exported("yarn")
@@ -40,7 +39,7 @@ export class YarnPackageManager extends BasePackageManager implements INodePacka
4039
const cwd = pathToSave;
4140

4241
try {
43-
await this._getYarnInstallResult(params, cwd);
42+
await this.processPackageManagerInstall(params, { cwd });
4443

4544
if (isInstallingAllDependencies) {
4645
return null;
@@ -92,7 +91,7 @@ export class YarnPackageManager extends BasePackageManager implements INodePacka
9291
@exported("yarn")
9392
public async getRegistryPackageData(packageName: string): Promise<any> {
9493
const registry = await this.$childProcess.exec(`yarn config get registry`);
95-
const url = registry.trim() + packageName;
94+
const url = `${registry.trim()}/${packageName}`;
9695
this.$logger.trace(`Trying to get data from yarn registry for package ${packageName}, url is: ${url}`);
9796
const responseData = (await this.$httpClient.httpRequest(url)).body;
9897
this.$logger.trace(`Successfully received data from yarn registry for package ${packageName}. Response data is: ${responseData}`);
@@ -101,21 +100,6 @@ export class YarnPackageManager extends BasePackageManager implements INodePacka
101100
return jsonData;
102101
}
103102

104-
private async _getYarnInstallResult(params: string[], cwd: string): Promise<ISpawnResult> {
105-
return new Promise<ISpawnResult>(async (resolve, reject) => {
106-
const npmExecutable = this.getNpmExecutableName(this.$hostInfo.isWindows);
107-
const stdioValue = isInteractive() ? "inherit" : "pipe";
108-
const childProcess = this.$childProcess.spawn(npmExecutable, params, { cwd, stdio: stdioValue });
109-
try {
110-
await this.processPackageManagerInstall(childProcess, this.$hostInfo.isWindows, params);
111-
resolve();
112-
} catch (e) {
113-
reject(e);
114-
}
115-
116-
});
117-
}
118-
119103
@exported("yarn")
120104
getCachePath(): Promise<string> {
121105
throw new Error("Method not implemented.");

0 commit comments

Comments
 (0)