Skip to content

Commit

Permalink
Extract typescript installer to utils
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbranch committed Mar 5, 2020
1 parent b9c965f commit 92af4cc
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 100 deletions.
1 change: 1 addition & 0 deletions packages/header-parser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped-tools/issues"
},
"dependencies": {
"@definitelytyped/utils": "^1.0.0",
"@types/parsimmon": "^1.10.1",
"parsimmon": "^1.13.0"
}
Expand Down
71 changes: 1 addition & 70 deletions packages/header-parser/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert = require("assert");
import pm = require("parsimmon");
import { AllTypeScriptVersion, TypeScriptVersion } from "@definitelytyped/utils";

/*
Example:
Expand All @@ -10,75 +10,6 @@ Example:
// TypeScript Version: 2.1
*/

/** Parseable but unsupported TypeScript versions. */
export type UnsupportedTypeScriptVersion =
| "2.0" | "2.1" | "2.2" | "2.3" | "2.4" | "2.5" | "2.6" | "2.7";
/**
* Parseable and supported TypeScript versions.
* Only add to this list if we will support this version on DefinitelyTyped.
*/
export type TypeScriptVersion =
| "2.8" | "2.9"
| "3.0" | "3.1" | "3.2" | "3.3" | "3.4" | "3.5" | "3.6" | "3.7" | "3.8" | "3.9";
export type AllTypeScriptVersion = UnsupportedTypeScriptVersion | TypeScriptVersion;
export namespace TypeScriptVersion {
export const supported: readonly TypeScriptVersion[] =
["2.8", "2.9",
"3.0", "3.1", "3.2", "3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9"];
export const unsupported: readonly UnsupportedTypeScriptVersion[] =
["2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7"];
export const all: readonly AllTypeScriptVersion[] = [...unsupported, ...supported];
export const lowest = supported[0];
/** Latest version that may be specified in a `// TypeScript Version:` header. */
export const latest = supported[supported.length - 1];

/** @deprecated */
export function isPrerelease(_version: TypeScriptVersion): boolean {
return false;
}

export function isSupported(v: AllTypeScriptVersion): v is TypeScriptVersion {
return supported.indexOf(v as TypeScriptVersion) > -1;
}

export function range(min: TypeScriptVersion): ReadonlyArray<TypeScriptVersion> {
return supported.filter(v => v >= min);
}

const supportedTags: readonly string[] = [
"ts2.8",
"ts2.9",
"ts3.0",
"ts3.1",
"ts3.2",
"ts3.3",
"ts3.4",
"ts3.5",
"ts3.6",
"ts3.7",
"ts3.8",
"ts3.9",
"latest",
];

/** List of NPM tags that should be changed to point to the latest version. */
export function tagsToUpdate(v: TypeScriptVersion): ReadonlyArray<string> {
const idx = supportedTags.indexOf(`ts${v}`);
assert(idx !== -1);
return supportedTags.slice(idx);
}

export function previous(v: TypeScriptVersion): TypeScriptVersion | undefined {
const index = supported.indexOf(v);
assert(index !== -1);
return index === 0 ? undefined : supported[index - 1];
}

export function isRedirectable(v: TypeScriptVersion): boolean {
return all.indexOf(v) >= all.indexOf("3.1");
}
}

export interface Header {
readonly nonNpm: boolean;
readonly libraryName: string;
Expand Down
5 changes: 4 additions & 1 deletion packages/header-parser/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
"include": ["src"],
"references": [
{ "path": "../utils" }
]
}

8 changes: 4 additions & 4 deletions packages/publisher/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 6 additions & 25 deletions packages/publisher/src/tester/test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
import {
assertDefined,
CrashRecoveryState,
exec,
execAndThrowErrors,
joinPaths,
logUncaughtErrors,
Expand All @@ -31,9 +30,9 @@ import {
FS,
Semver,
npmInstallFlags,
LoggerWithErrors,
Logger,
flatMapIterable,
installAllTypeScriptVersions,
} from "@definitelytyped/utils";

import { allDependencies, getAffectedPackages } from "./get-affected-packages";
Expand Down Expand Up @@ -187,7 +186,11 @@ async function doInstalls(allPackages: AllPackages, packages: Iterable<TypingsDa
}
}

await runCommand(console, undefined, require.resolve("dtslint"), ["--installAll"]);
try {
await installAllTypeScriptVersions();
} catch (error) {
console.error(error);
}
}

function directoryPath(typesPath: string, pkg: TypingsData): string {
Expand Down Expand Up @@ -282,28 +285,6 @@ async function doRunTests(
throw new Error(`The following packages had errors: ${allFailures.map(e => e[0]).join(", ")}`);
}

interface TesterError {
message: string;
}

async function runCommand(log: LoggerWithErrors, cwd: string | undefined, cmd: string, args: string[]): Promise<TesterError | undefined> {
const nodeCmd = `node ${cmd} ${args.join(" ")}`;
log.info(`Running: ${nodeCmd}`);
try {
const { error, stdout, stderr } = await exec(nodeCmd, cwd);
if (stdout) {
log.info(stdout);
}
if (stderr) {
log.error(stderr);
}

return error && { message: `${error.message}\n${stdout}\n${stderr}` };
} catch (e) {
return e as TesterError;
}
}

/** Returns all immediate subdirectories of the root directory that have changed. */
export function gitChanges(diffs: GitDiff[]): PackageId[] {
const changedPackages = new Map<string, Map<string, DependencyVersion>>();
Expand Down
1 change: 1 addition & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from "./miscellany";
export * from "./process";
export * from "./progress";
export * from "./semver";
export * from "./typescript-installer";
152 changes: 152 additions & 0 deletions packages/utils/src/typescript-installer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import assert = require("assert");
import { exec } from "child_process";
import * as fs from "fs-extra";
import * as os from "os";
import * as path from "path";

const installsDir = path.join(os.homedir(), ".dts", "typescript-installs");

/** Parseable but unsupported TypeScript versions. */
export type UnsupportedTypeScriptVersion =
| "2.0" | "2.1" | "2.2" | "2.3" | "2.4" | "2.5" | "2.6" | "2.7";
/**
* Parseable and supported TypeScript versions.
* Only add to this list if we will support this version on DefinitelyTyped.
*/
export type TypeScriptVersion =
| "2.8" | "2.9"
| "3.0" | "3.1" | "3.2" | "3.3" | "3.4" | "3.5" | "3.6" | "3.7" | "3.8" | "3.9";

export type AllTypeScriptVersion = UnsupportedTypeScriptVersion | TypeScriptVersion;

export type TsVersion = TypeScriptVersion | "next" | "local";

export namespace TypeScriptVersion {
export const supported: readonly TypeScriptVersion[] =
["2.8", "2.9",
"3.0", "3.1", "3.2", "3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9"];
export const unsupported: readonly UnsupportedTypeScriptVersion[] =
["2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7"];
export const all: readonly AllTypeScriptVersion[] = [...unsupported, ...supported];
export const lowest = supported[0];
/** Latest version that may be specified in a `// TypeScript Version:` header. */
export const latest = supported[supported.length - 1];

/** @deprecated */
export function isPrerelease(_version: TypeScriptVersion): boolean {
return false;
}

export function isSupported(v: AllTypeScriptVersion): v is TypeScriptVersion {
return supported.indexOf(v as TypeScriptVersion) > -1;
}

export function range(min: TypeScriptVersion): ReadonlyArray<TypeScriptVersion> {
return supported.filter(v => v >= min);
}

const supportedTags: readonly string[] = [
"ts2.8",
"ts2.9",
"ts3.0",
"ts3.1",
"ts3.2",
"ts3.3",
"ts3.4",
"ts3.5",
"ts3.6",
"ts3.7",
"ts3.8",
"ts3.9",
"latest",
];

/** List of NPM tags that should be changed to point to the latest version. */
export function tagsToUpdate(v: TypeScriptVersion): ReadonlyArray<string> {
const idx = supportedTags.indexOf(`ts${v}`);
assert(idx !== -1);
return supportedTags.slice(idx);
}

export function previous(v: TypeScriptVersion): TypeScriptVersion | undefined {
const index = supported.indexOf(v);
assert(index !== -1);
return index === 0 ? undefined : supported[index - 1];
}

export function isRedirectable(v: TypeScriptVersion): boolean {
return all.indexOf(v) >= all.indexOf("3.1");
}
}

export async function installAllTypeScriptVersions() {
for (const v of TypeScriptVersion.supported) {
// manually install typescript@next outside the loop
if (v === TypeScriptVersion.supported[TypeScriptVersion.supported.length - 1]) { continue; }
await install(v);
}
await installTypeScriptNext();
}

export async function installTypeScriptNext() {
await install("next");
}

async function install(version: TsVersion): Promise<void> {
if (version === "local") {
return;
}
const dir = installDir(version);
if (!await fs.pathExists(dir)) {
console.log(`Installing to ${dir}...`);
await fs.mkdirp(dir);
await fs.writeJson(path.join(dir, "package.json"), packageJson(version));
await execAndThrowErrors("npm install --ignore-scripts --no-shrinkwrap --no-package-lock --no-bin-links", dir);
console.log("Installed!");
console.log("");
}
}

export function cleanTypeScriptInstalls(): Promise<void> {
return fs.remove(installsDir);
}

export function typeScriptPath(version: TsVersion, tsLocal: string | undefined): string {
if (version === "local") {
return tsLocal! + "/typescript.js";
}
return path.join(installDir(version), "node_modules", "typescript");
}

function installDir(version: TsVersion): string {
assert(version !== "local");
return path.join(installsDir, version);
}

/** Run a command and return the stdout, or if there was an error, throw. */
async function execAndThrowErrors(cmd: string, cwd?: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
exec(cmd, { encoding: "utf8", cwd }, (err, _stdout, stderr) => {
if (stderr) {
console.error(stderr);
}

if (err) {
reject(err);
} else {
resolve();
}
});
});
}

function packageJson(version: TsVersion): {} {
return {
description: `Installs typescript@${version}`,
repository: "N/A",
license: "MIT",
dependencies: {
typescript: version,
},
};
}

0 comments on commit 92af4cc

Please sign in to comment.