Merge branch 'master' into daschult/urltokenizerstate

This commit is contained in:
Sergey Shandar 2018-12-06 10:09:01 -08:00 коммит произвёл GitHub
Родитель 98b469b1fe 6f33a696d0
Коммит 70a83f45b3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 3 добавлений и 368 удалений

Просмотреть файл

@ -1,351 +0,0 @@
import * as fs from "fs";
import * as path from "path";
import { execSync } from "child_process";
export interface PackageFolder {
folderPath: string;
extraFilePaths?: string[];
isLernaPackage?: boolean;
}
function log(filePath: string, message: string): void {
console.log(`[${filePath}] - ${message}`);
}
/**
* Get whether or not the node_modules folder should be refreshed based on the command line
* arguments.
* @param argv The command line arguments that were provided.
* @returns Whether or not the node_modules folder should be refreshed.
*/
export function shouldForceRefresh(argv: string[]): boolean {
let result = false;
if (argv) {
for (const arg of argv) {
const argLower: string = arg && arg.toLocaleLowerCase();
if (argLower === "-f" || argLower === "-force" || argLower === "--force") {
result = true;
break;
}
}
}
return result;
}
export function resolvePath(...paths: string[]): string {
return path.resolve(...paths).split("\\").join("/");
}
function exists(path: string | undefined): boolean {
if (!path) {
return false;
}
return fs.existsSync(path);
}
/**
* Delete the file at the provided file path.
* @param {string} filePath The path to the file to delete.
*/
function deleteFile(filePath: string): void {
fs.unlinkSync(filePath);
}
/**
* Delete the folder at the provided folder path.
* @param {string} folderPath The path to the folder to delete.
*/
function deleteFolder(folderPath: string): void {
try {
fs.rmdirSync(folderPath);
} catch (error) {
if (error.code === "ENOTEMPTY") {
const folderEntryPaths: string[] = fs.readdirSync(folderPath);
for (const entryName of folderEntryPaths) {
const entryPath: string = resolvePath(folderPath, entryName);
const entryStats: fs.Stats = fs.lstatSync(entryPath);
if (entryStats.isDirectory()) {
deleteFolder(entryPath);
} else {
deleteFile(entryPath);
}
}
fs.rmdirSync(folderPath);
} else {
throw error;
}
}
}
/**
* Read the contents of text file at the provided filePath.
* @param {string} filePath The path to the text file to read.
* @returns {string} The text contents of the text file at the provided filePath.
*/
function readTextFileContents(filePath: string): string {
return fs.readFileSync(filePath, { encoding: "utf8" });
}
/**
* Execute the provided command on the shell synchronously.
* @param {string} command The command to execute.
* @param {string} workingDirectory The working directory to execute the command in.
* @returns {void}
*/
function execute(command: string, workingDirectory: string): void {
log(workingDirectory, `Running "${command}"...`);
execSync(command, { cwd: workingDirectory, stdio: [0, 1, 2] });
}
/**
* Get the absolute path to this repository's folder path.
* @returns {string} The absolute path to this repository's folder path.
*/
export function getThisRepositoryFolderPath(): string {
return resolvePath(__dirname, "..");
}
/**
* Get the absolute path to the package.json in this repository.
* @returns {string} The absolute path to the package.json.
*/
function getPackageJsonFilePath(packageFolder: string): string {
return resolvePath(packageFolder, "package.json");
}
function getPackageNameFromPackageJson(packageJsonFilePath: string): string {
const packageJson: { name: string } = getPackageJson(packageJsonFilePath);
return packageJson.name;
}
/**
* Get the absolute path to the local clone of the repository with the provided name.
* @param {string} repoName The name of the repository.
* @returns {string} The absolute path to the local clone of the repository.
*/
export function getLocalRepositoryPath(repoName: string): string | undefined {
const repositoriesRoot: string = resolvePath(getThisRepositoryFolderPath(), "..");
const repositoryPaths: string[] = fs.readdirSync(repositoriesRoot).map(childDir => resolvePath(repositoriesRoot, childDir));
for (const repositoryPath of repositoryPaths) {
const packageJsonPath = getPackageJsonFilePath(repositoryPath);
if (!fs.existsSync(packageJsonPath)) {
continue;
}
const packageName = getPackageNameFromPackageJson(packageJsonPath);
if (packageName === repoName) {
return repositoryPath;
}
}
return undefined;
}
/**
* Get the package.json file contents parsed as a JSON object.
* @param {string=} packageJsonFilePath The path to the package.json file to read. If this is not
* provided, then the package.json file at the root of this repository will be used.
* @returns {{}} The parsed package.json file contents.
*/
function getPackageJson(packageJsonFilePath: string): any {
return JSON.parse(readTextFileContents(packageJsonFilePath));
}
/**
* Get the dependencies from the provided dependencies dictionary that have local clones.
* @param {{ [packageName: string]: string }} dependencies A dictionary of package names to package
* versions.
* @param {string[]} clonedRepositoryNames The array to put the names of the local cloned
* repositories into.
* @returns {void}
*/
function getClonedRepositories(dependencies?: { [packageName: string]: string }): string[] {
const clonedRepositoryNames: string[] = [];
if (dependencies) {
for (const dependencyName in dependencies) {
if (clonedRepositoryNames.indexOf(dependencyName) === -1) {
const repoFolderPath = getLocalRepositoryPath(dependencyName);
if (exists(repoFolderPath)) {
clonedRepositoryNames.push(dependencyName);
}
}
}
}
return clonedRepositoryNames;
}
/**
* Run a script with the provided name in the local clone of the repository with the provided name.
* @param {string} repoName The name of the repository to run the script in.
* @param {string} scriptName The name of the script to run in the local repository.
* @returns {void}
*/
export function runLocalRepositoryNPMScript(repoName: string, scriptName: string): void {
const repoFolderPath: string | undefined = getLocalRepositoryPath(repoName);
if (!repoFolderPath) {
return;
}
const packageJsonFilePath: string = getPackageJsonFilePath(repoFolderPath);
const packageJson: any = getPackageJson(packageJsonFilePath);
const repoScripts: any = packageJson.scripts;
if (repoScripts && repoScripts[scriptName]) {
execute(`npm run ${scriptName}`, repoFolderPath);
} else {
log(packageJsonFilePath, `No script named "${scriptName}" is defined.`);
}
}
/**
* Get the npm package version of the package with the provided name at the provided tag.
* @param {string} packageName The name of the package.
* @param {string} tag The tag of the version to retrieve.
* @returns {string?} The version of the provided package at the provided tag.
*/
export function getNpmPackageVersion(packageName: string, tag: string): string | undefined {
const npmViewResult: any = JSON.parse(execSync(`npm view ${packageName} --json`, { stdio: ["pipe", "pipe", "ignore"] }).toString());
return npmViewResult["dist-tags"][tag];
}
/**
* Update the dependency versions in the files at the provided codeFilePaths.
* @param {string[]} codeFilePath The paths to the code files that should be updated.
* @param {string} dependencyName The name of the dependency to update.
* @param {RegExp} regularExpression The regular expression to use to find the dependency name and
* version in the code file's contents.
* @param {string} newValue The replacement string that will replace the text that matches the
* provided regularExpression.
* @param {string} newDependencyVersion The version of the dependency to set in the provided code
* files.
*/
function updateGeneratedPackageDependencyVersion(codeFilePath: string, dependencyName: string, newDependencyVersion: string): boolean {
let fileChanged = false;
codeFilePath = resolvePath(codeFilePath);
if (exists(codeFilePath)) {
const originalCodeFileContents: string = readTextFileContents(codeFilePath);
let codeFileContents: string = originalCodeFileContents;
codeFileContents = regularExpressionReplace(
codeFilePath,
codeFileContents,
dependencyName,
new RegExp(`\\\\"${dependencyName}\\\\": \\\\"(.*?)\\\\"`),
`\\"${dependencyName}\\": \\"${newDependencyVersion}\\"`,
newDependencyVersion);
codeFileContents = regularExpressionReplace(
codeFilePath,
codeFileContents,
dependencyName,
new RegExp(`"${dependencyName}": "(.*?)"`),
`"${dependencyName}": "${newDependencyVersion}"`,
newDependencyVersion);
if (codeFileContents !== originalCodeFileContents) {
fileChanged = true;
fs.writeFileSync(codeFilePath, codeFileContents);
}
}
return fileChanged;
}
function regularExpressionReplace(filePath: string, fileContents: string, dependencyName: string, regularExpression: RegExp, newValue: string, newDependencyVersion: string): string {
let newFileContents: string = fileContents;
const match: RegExpMatchArray | null = fileContents.match(regularExpression);
if (match) {
if (match[1] === newDependencyVersion) {
log(filePath, `"${dependencyName}" is already set to "${newDependencyVersion}".`);
} else {
log(filePath, `Changing "${dependencyName}" version from "${match[1]}" to "${newDependencyVersion}".`);
newFileContents = fileContents.replace(regularExpression, newValue);
}
}
return newFileContents;
}
export function updateLocalDependencies(packageFolders: PackageFolder[], localDependencyNPMScript: string, getNewDependencyVersion: (dependencyName: string) => (string | undefined)): void {
const forceRefresh: boolean = shouldForceRefresh(process.argv);
for (const packageFolder of packageFolders) {
const packageFolderPath: string = packageFolder.folderPath;
const packageJson: any = getPackageJson(resolvePath(packageFolderPath, "package.json"));
const localDependencies: string[] = getClonedRepositories(packageJson.dependencies);
const localDevDependencies: string[] = getClonedRepositories(packageJson.devDependencies);
const allLocalDependencies: string[] = localDependencies.concat(localDevDependencies);
for (const localDependency of allLocalDependencies) {
runLocalRepositoryNPMScript(localDependency, localDependencyNPMScript);
}
const dependenciesToRefresh: string[] = [];
for (const localDependency of allLocalDependencies) {
if (updateLocalDependency(packageFolder, localDependency, getNewDependencyVersion)) {
dependenciesToRefresh.push(localDependency);
}
}
if (forceRefresh || dependenciesToRefresh.length > 0) {
if (packageFolder.isLernaPackage) {
log(packageFolderPath, `Not refreshing dependencies since this is a lerna package.`);
} else {
const packageLockFilePath = resolvePath(packageFolderPath, "package-lock.json");
if (exists(packageLockFilePath)) {
log(packageLockFilePath, `Deleting...`);
deleteFile(packageLockFilePath);
}
const nodeModulesFolderPath = resolvePath(packageFolderPath, "node_modules");
if (exists(nodeModulesFolderPath)) {
log(nodeModulesFolderPath, `Deleting...`);
deleteFolder(nodeModulesFolderPath);
}
execute("npm install", packageFolderPath);
}
}
}
}
function updateLocalDependency(packageFolder: PackageFolder, dependencyName: string, getNewDependencyVersion: (dependencyName: string) => (string | undefined)): boolean {
const newDependencyVersion: string = getNewDependencyVersion(dependencyName) || "";
const packageFolderPath: string = packageFolder.folderPath;
const localDependencyUpdated = updateGeneratedPackageDependencyVersion(
resolvePath(packageFolderPath, "package.json"),
dependencyName,
newDependencyVersion);
updateGeneratedPackageDependencyVersion(
resolvePath(packageFolderPath, "README.md"),
dependencyName,
newDependencyVersion);
if (packageFolder.extraFilePaths) {
for (const extraFilePath of packageFolder.extraFilePaths) {
updateGeneratedPackageDependencyVersion(
resolvePath(packageFolderPath, extraFilePath),
dependencyName,
newDependencyVersion);
}
}
return localDependencyUpdated;
}
export function getLocalDependencyVersion(dependencyName: string): string {
return `file:${getLocalRepositoryPath(dependencyName)}`;
}
export function getLatestDependencyVersion(dependencyName: string): string | undefined {
return addCaretPrefix(getNpmPackageVersion(dependencyName, "latest"));
}
function addCaretPrefix(version: string | undefined): string | undefined {
return version ? `^${version}` : version;
}

Просмотреть файл

@ -1,4 +0,0 @@
import * as dependencies from "./dependencies";
import * as repository from "./repository";
dependencies.updateLocalDependencies(repository.packageFolders, "latest", dependencies.getLatestDependencyVersion);

Просмотреть файл

@ -1,4 +0,0 @@
import * as dependencies from "./dependencies";
import * as repository from "./repository";
dependencies.updateLocalDependencies(repository.packageFolders, "local", dependencies.getLocalDependencyVersion);

Просмотреть файл

@ -1,7 +0,0 @@
import * as dependencies from "./dependencies";
export const packageFolders: dependencies.PackageFolder[] = [
{
folderPath: dependencies.getThisRepositoryFolderPath()
}
];

Просмотреть файл

@ -56,6 +56,7 @@
"xml2js": "^0.4.19"
},
"devDependencies": {
"@ts-common/azure-js-dev-tools": "^0.1.3",
"@types/chai": "^4.1.7",
"@types/express": "^4.16.0",
"@types/form-data": "^2.2.1",
@ -116,8 +117,8 @@
"test:unit": "ts-node ./.scripts/unit.ts",
"test:server": "ts-node -T testserver",
"publish-preview": "mocha --no-colors && shx rm -rf dist/test && node ./.scripts/publish",
"local": "ts-node ./.scripts/local.ts",
"latest": "ts-node ./.scripts/latest.ts",
"local": "npm explore @ts-common/azure-js-dev-tools -- npm run local",
"latest": "npm explore @ts-common/azure-js-dev-tools -- npm run latest",
"prepack": "npm i && npm run build"
},
"sideEffects": false