This commit is contained in:
Garrett Serack 2019-09-05 16:11:28 -07:00
Родитель 0fa6284be2
Коммит 95fc125683
17 изменённых файлов: 388 добавлений и 360 удалений

70
.scripts/for-each.js Normal file
Просмотреть файл

@ -0,0 +1,70 @@
var cp = require("child_process");
var fs = require("fs");
var path = require("path");
function read(filename) {
const txt = fs.readFileSync(filename, "utf8")
.replace(/\r/gm, "")
.replace(/\n/gm, "«")
.replace(/\/\*.*?\*\//gm, "")
.replace(/«/gm, "\n")
.replace(/\s+\/\/.*/g, "");
return JSON.parse(txt);
}
const repo = `${__dirname}/..`;
const rush = read(`${repo}/rush.json`);
const pjs = {};
function forEachProject(onEach) {
// load all the projects
for (const each of rush.projects) {
const packageName = each.packageName;
const projectFolder = path.resolve(`${repo}/${each.projectFolder}`);
const project = require(`${projectFolder}/package.json`);
onEach(packageName, projectFolder, project);
}
}
function npmForEach(cmd) {
let count = 0;
let exitCode = 0;
const result = {};
const procs = [];
const t1 = process.uptime() * 100;
forEachProject((name, location, project) => {
// checks for the script first
if (project.scripts[cmd]) {
count++;
const proc = cp.spawn("npm", ["--silent", "run", cmd], { cwd: location, shell: true, stdio: "inherit" });
procs.push(proc);
result[name] = {
name, location, project, proc,
};
}
});
procs.forEach(proc => proc.on("close", (code, signal) => {
count--;
exitCode += code;
if (count === 0) {
const t2 = process.uptime() * 100;
console.log('---------------------------------------------------------');
if (exitCode !== 0) {
console.log(` Done : command '${cmd}' - ${Math.floor(t2 - t1) / 100} s -- Errors ${exitCode} `)
} else {
console.log(` Done : command '${cmd}' - ${Math.floor(t2 - t1) / 100} s -- No Errors `)
}
console.log('---------------------------------------------------------');
process.exit(exitCode);
}
}));
return result;
}
module.exports.forEachProject = forEachProject;
module.exports.npm = npmForEach;

2
.scripts/npm-run.js Normal file
Просмотреть файл

@ -0,0 +1,2 @@
// Runs the npm run command on each project that has it.
require('./for-each').npm(process.argv[2]);

102
.scripts/sync-versions.js Normal file
Просмотреть файл

@ -0,0 +1,102 @@
var fs = require('fs');
function read(filename) {
const txt = fs.readFileSync(filename, 'utf8')
.replace(/\r/gm, '')
.replace(/\n/gm, '«')
.replace(/\/\*.*?\*\//gm, '')
.replace(/«/gm, '\n')
.replace(/\s+\/\/.*/g, '');
return JSON.parse(txt);
}
function versionToInt(ver) {
let v = ver.replace(/[^\d\.]/g, '').split('.').slice(0, 3);
while (v.length < 3) {
v.unshift(0);
}
let n = 0;
for (let i = 0; i < v.length; i++) {
n = n + ((2 ** (i * 16)) * parseInt(v[v.length - 1 - i]))
}
return n;
}
const rush = read(`${__dirname}/../../rush.json`);
const pjs = {};
// load all the projects
for (const each of rush.projects) {
const packageName = each.packageName;
const projectFolder = each.projectFolder;
pjs[packageName] = require(`${__dirname}/../../${projectFolder}/package.json`);
}
// verify that peer dependencies are the same version as they are building.
for (const pj of Object.getOwnPropertyNames(pjs)) {
const each = pjs[pj];
for (const dep in each.dependencies) {
const ref = pjs[dep];
if (ref) {
each.dependencies[dep] = `~${ref.version}`;
}
}
}
function recordDeps(dependencies) {
for (const packageName in dependencies) {
const packageVersion = dependencies[packageName];
if (packageList[packageName]) {
// same version?
if (packageList[packageName] === packageVersion) {
continue;
}
// pick the higher one
const v = versionToInt(packageVersion);
if (v === 0) {
console.error(`Unparsed version ${packageName}:${packageVersion}`);
process.exit(1);
}
const v2 = versionToInt(packageList[packageName]);
if (v > v2) {
packageList[packageName] = packageVersion;
}
} else {
packageList[packageName] = packageVersion;
}
}
}
function fixDeps(pj, dependencies) {
for (const packageName in dependencies) {
if (dependencies[packageName] !== packageList[packageName]) {
console.log(`updating ${pj}:${packageName} from '${dependencies[packageName]}' to '${packageList[packageName]}'`)
dependencies[packageName] = packageList[packageName];
}
}
}
const packageList = {};
// now compare to see if someone has an exnternal package with different version
// than everyone else.
for (const pj of Object.getOwnPropertyNames(pjs)) {
const each = pjs[pj];
recordDeps(each.dependencies);
recordDeps(each.devDependencies);
}
for (const pj of Object.getOwnPropertyNames(pjs)) {
const each = pjs[pj];
fixDeps(pj, each.dependencies);
fixDeps(pj, each.devDependencies);
}
// write out the results.
for (const each of rush.projects) {
const packageName = each.packageName;
const projectFolder = each.projectFolder;
fs.writeFileSync(`${__dirname}/../../${projectFolder}/package.json`, JSON.stringify(pjs[packageName], null, 2));
}
console.log("project.json files updated");

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

@ -0,0 +1,29 @@
$ErrorActionPreference = 'silentlycontinue'
write-host -fore green "Verifying requirements to build.`n"
write-host -fore cyan -NoNewline " Rush: "
$rush = get-command rush
if ( -not $rush ) {
write-host -fore red "NOT INSTALLED."
write-host -fore cyan " You must install 'rush' to continue:"
write-host -fore yellow ' > npm install -g "@microsoft/rush"'
write-host -fore red "`n`n`n"
exit 1
}
write-host -fore green "INSTALLED"
write-host -fore green "`nAll requirements met.`n"
write-host -fore cyan "Common rush commands:"
write-host -fore yellow ' > rush update ' -NoNewline
write-host -fore gray ' # installs package dependencies '
write-host -fore yellow ' > rush rebuild ' -NoNewline
write-host -fore gray ' # rebuilds all libraries'
write-host -fore yellow ' > rush watch ' -NoNewline
write-host -fore gray ' # continual build when files change'
write-host "`n`n`n"
exit 0

25
.scripts/watch.js Normal file
Просмотреть файл

@ -0,0 +1,25 @@
var cp = require('child_process');
require('./for-each').forEachProject((packageName, projectFolder, project) => {
if (project.scripts.watch) {
console.log(`npm run watch {cwd: ${__dirname}/../${projectFolder}}`);
const proc = cp.spawn('npm', ['run', 'watch'], { cwd: projectFolder, shell: true, stdio: "inherit" });
proc.on("error", (c, s) => {
console.log(packageName);
console.error(c);
console.error(s);
});
proc.on('exit', (c, s) => {
console.log(packageName);
console.error(c);
console.error(s);
});
proc.on('message', (c, s) => {
console.log(packageName);
console.error(c);
console.error(s);
})
}
});

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

@ -22,17 +22,41 @@
"summary": "reset the version in the package.json files to .0",
"enableParallelism": true
},
{
"commandKind": "global",
"name": "sync-versions",
"summary": "sync versions of sibling projects",
"shellCommand": "node .scripts/sync-versions.js"
},
{
"commandKind": "global",
"name": "watch",
"summary": "run npm watch on all projects",
"shellCommand": "node .scripts/watch.js"
},
{
"commandKind": "global",
"name": "clean",
"summary": "run npm clean on all projects",
"shellCommand": "node .scripts/npm-run.js clean"
},
{
"commandKind": "global",
"name": "test",
"summary": "run all npm test",
"shellCommand": "node .scripts/npm-run.js test"
},
{
"commandKind": "global",
"name": "fix",
"summary": "run all npm fix",
"shellCommand": "node common/scripts/fix.js"
"shellCommand": "node .scripts/npm-run.js eslint-fix"
},
{
"commandKind": "global",
"name": "lint",
"summary": "run all npm eslint",
"shellCommand": "node common/scripts/eslint.js"
"summary": "run all npm lint",
"shellCommand": "node .scripts/npm-run.js eslint"
}
// {
// /**
@ -82,31 +106,6 @@
// */
// "ignoreMissingScript": false
// },
,
{
"commandKind": "global",
"name": "sync-versions",
"summary": "sync versions of sibling projects",
"shellCommand": "node common/scripts/sync-versions.js"
},
{
"commandKind": "global",
"name": "watch",
"summary": "run npm watch on all projects",
"shellCommand": "node common/scripts/watch.js"
},
{
"commandKind": "global",
"name": "clean",
"summary": "run npm clean on all projects",
"shellCommand": "node common/scripts/clean.js"
},
{
"commandKind": "global",
"name": "test",
"summary": "run all npm test",
"shellCommand": "node common/scripts/test.js"
}
//
// {
// /**
@ -124,7 +123,7 @@
// * that contains rush.json. If custom parameters are associated with this command, their
// * values will be appended to the end of this string.
// */
// "shellCommand": "node common/scripts/my-global-command.js"
// "shellCommand": "node .scripts/my-global-command.js"
// }
],
/**

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

@ -1 +0,0 @@
require('./for-each').npm('clean');

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

@ -1 +0,0 @@
require('./for-each').npm('eslint');

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

@ -1 +0,0 @@
require('./for-each').npm('eslint-fix');

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

@ -1,47 +0,0 @@
var cp = require("child_process");
var fs = require("fs");
var path = require("path");
function read(filename) {
const txt = fs.readFileSync(filename, "utf8")
.replace(/\r/gm, "")
.replace(/\n/gm, "«")
.replace(/\/\*.*?\*\//gm, "")
.replace(/«/gm, "\n")
.replace(/\s+\/\/.*/g, "");
return JSON.parse(txt);
}
const rush = read(`${__dirname}/../../rush.json`);
const pjs = {};
function forEachProject(onEach) {
// load all the projects
for (const each of rush.projects) {
const packageName = each.packageName;
const projectFolder = path.resolve(`${__dirname}/../../${each.projectFolder}`);
const project = require(`${projectFolder}/package.json`);
onEach(packageName, projectFolder, project);
}
}
function npmForEach(cmd) {
const result = {};
forEachProject((name, location, project) => {
if (project.scripts[cmd]) {
const proc = cp.spawn("npm", ['--silent',"run", cmd], { cwd: location, shell: true, stdio: "inherit" });
proc.on("close", (code, signal) => {
if (code !== 0) {
process.exit(code);
}
});
result[name] = {
name, location, project, proc,
};
}
});
return result;
}
module.exports.forEachProject = forEachProject;
module.exports.npm = npmForEach;

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

@ -1,121 +0,0 @@
var fs = require('fs');
function read(filename) {
const txt =fs.readFileSync(filename, 'utf8')
.replace(/\r/gm, '')
.replace(/\n/gm, '«')
.replace(/\/\*.*?\*\//gm,'')
.replace(/«/gm, '\n')
.replace(/\s+\/\/.*/g, '');
return JSON.parse( txt);
}
function versionToInt(ver) {
let v = ver.replace(/[^\d\.]/g,'').split('.').slice(0,3);
while( v.length < 3) {
v.unshift(0);
}
let n = 0 ;
for( let i =0; i< v.length;i++ ) {
n = n + ((2**(i*16))*parseInt(v[v.length-1 - i]))
}
return n;
}
const rush =read(`${__dirname}/../../rush.json`);
const pjs = {};
// load all the projects
for( const each of rush.projects ) {
const packageName = each.packageName;
const projectFolder = each.projectFolder;
pjs[packageName] = require(`${__dirname}/../../${projectFolder}/package.json`);
}
function setPeerDependencies(dependencies) {
for( const dep in dependencies ) {
const ref = pjs[dep];
if( ref ) {
if(dependencies[dep] !== `~${ref.version}` ) {
console.log(`updating peer depedency ${dep} to ~${ref.version}`);
dependencies[dep] = `~${ref.version}`;
}
}
}
}
// verify that peer dependencies are the same version as they are building.
for( const pj of Object.getOwnPropertyNames(pjs) ){
const each = pjs[pj];
setPeerDependencies(each.dependencies );
setPeerDependencies(each.devDependencies );
if( each['static-link']) {
setPeerDependencies(each['static-link'].devDependencies );
}
}
function recordDeps(dependencies) {
for( const packageName in dependencies ) {
const packageVersion = dependencies[packageName];
if( packageList[packageName] ) {
// same version?
if( packageList[packageName] === packageVersion ) {
continue;
}
// pick the higher one
const v = versionToInt(packageVersion);
if( v === 0) {
console.error(`Unparsed version ${packageName}:${packageVersion}`);
process.exit(1);
}
const v2 = versionToInt(packageList[packageName]);
if( v > v2 ) {
packageList[packageName] = packageVersion;
}
} else {
packageList[packageName] = packageVersion;
}
}
}
function fixDeps(pj,dependencies) {
for( const packageName in dependencies ) {
if( dependencies[packageName] !== packageList[packageName] ) {
console.log(`updating ${pj}:${packageName} from '${dependencies[packageName]}' to '${packageList[packageName]}'`)
dependencies[packageName] = packageList[packageName];
}
}
}
const packageList = {};
// now compare to see if someone has an exnternal package with different version
// than everyone else.
for( const pj of Object.getOwnPropertyNames(pjs) ){
const each = pjs[pj];
recordDeps(each.dependencies);
recordDeps(each.devDependencies);
if( each['static-link']) {
recordDeps(each['static-link'].dependencies);
}
}
for( const pj of Object.getOwnPropertyNames(pjs) ){
const each = pjs[pj];
fixDeps(pj,each.dependencies);
fixDeps(pj,each.devDependencies);
if( each['static-link']) {
fixDeps(pj,each['static-link'].dependencies);
}
}
// write out the results.
for( const each of rush.projects ) {
const packageName = each.packageName;
const projectFolder = each.projectFolder;
fs.writeFileSync(`${__dirname}/../../${projectFolder}/package.json`, JSON.stringify(pjs[packageName], null, 2 ));
}
console.log("project.json files updated");

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

@ -1 +0,0 @@
require('./for-each').npm('test');

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

@ -1,5 +0,0 @@
param( $npmauthtoken )
dir $PSScriptRoot/../temp/artifacts/packages/*.tgz |% {
& "$PSScriptRoot/../temp/pnpm-local/node_modules/.bin/pnpm" publish $_ --tag beta --scope access "--$npmauthtoken"
}

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

@ -1,47 +0,0 @@
var fs = require('fs');
var cp = require('child_process');
var pt = require('path');
function read(filename) {
const txt =fs.readFileSync(filename, 'utf8')
.replace(/\r/gm, '')
.replace(/\n/gm, '«')
.replace(/\/\*.*?\*\//gm,'')
.replace(/«/gm, '\n')
.replace(/\s+\/\/.*/g, '');
return JSON.parse( txt);
}
const rush =read(`${__dirname}/../../rush.json`);
const pjs = {};
// load all the projects
for( const each of rush.projects ) {
const packageName = each.packageName;
const projectFolder = each.projectFolder;
const project = require(`${__dirname}/../../${projectFolder}/package.json`);
if( project.scripts.watch ) {
console.log(`npm.cmd run watch {cwd: ${__dirname}/../../${projectFolder}}`);
const proc = cp.spawn('npm.cmd', ['run','watch'],{cwd: `${__dirname}/../../${projectFolder}`,shell:true,stdio:"inherit"});
const root = pt.resolve(`${__dirname}/../../${projectFolder}`);
proc.on("error", (c,s) => {
console.log(packageName);
console.error( c.replace(/(\w*.*\.ts:)/g, `${root}/$1`));
console.error( s.replace(/(\w*.*\.ts:)/g, `${root}/$1`));
});
proc.on('exit',(c,s)=> {
console.log(packageName);
console.error( c);
console.error( s);
});
proc.on('message',(c,s)=> {
console.log(packageName);
console.error( c.replace(/(\w*.*\.ts:)/g, `${root}/$1`));
console.error( s.replace(/(\w*.*\.ts:)/g, `${root}/$1`));
})
}
}

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

@ -733,9 +733,6 @@ export class Configuration {
configs = { ...configs };
configs['use-extension'] = { ...configs['use-extension'] };
// this keeps --use parameters in the configuration so that we can check if someone tried pull it in (powershell needed this)
configs['requesting-extensions'] = configs['requesting-extensions'] ? typeof configs['requesting-extensions'] === 'string' ? [configs['requesting-extensions']] : [...configs['requesting-extensions']] : [];
if (configs['licence-header']) {
configs['license-header'] = configs['licence-header'];
delete configs['licence-header'];
@ -747,7 +744,6 @@ export class Configuration {
use = [use];
}
if (Array.isArray(use)) {
configs['requesting-extensions'].push(...use);
const extMgr = await Configuration.extensionManager;
for (const useEntry of use) {
if (typeof useEntry === 'string') {
@ -894,126 +890,136 @@ export class Configuration {
// 5. resolve extensions
const extMgr = await Configuration.extensionManager;
const addedExtensions = new Set<string>();
const viewsToHandle: Array<ConfigurationView> = [createView()];
while (viewsToHandle.length > 0) {
const tmpView = <ConfigurationView>viewsToHandle.pop();
const additionalExtensions = tmpView.UseExtensions.filter(ext => !addedExtensions.has(ext.fullyQualified));
await addSegments([{ 'used-extension': tmpView.UseExtensions.map(x => x.fullyQualified) }]);
if (additionalExtensions.length === 0) {
continue;
}
// acquire additional extensions
for (const additionalExtension of additionalExtensions) {
try {
addedExtensions.add(additionalExtension.fullyQualified);
let ext = loadedExtensions[additionalExtension.fullyQualified];
// not yet loaded?
if (!ext) {
let localPath = untildify(additionalExtension.source);
// try resolving the package locally (useful for self-contained)
try {
const fileProbe = '/package.json';
localPath = require.resolve(additionalExtension.name + fileProbe); // have to resolve specific file - resolving a package by name will fail if no 'main' is present
localPath = localPath.slice(0, localPath.length - fileProbe.length);
} catch {
// no worries
}
// trim off the '@org' and 'autorest.' from the name.
const shortname = additionalExtension.name.split('/').last.replace(/^autorest\./ig, '');
const view = [...createView().GetNestedConfiguration(shortname)];
const enableDebugger = view.length > 0 ? <boolean>(view[0].GetEntry('debugger')) : false;
const resolveExtensions = async () => {
const viewsToHandle: Array<ConfigurationView> = [createView()];
while (viewsToHandle.length > 0) {
const tmpView = <ConfigurationView>viewsToHandle.pop();
const additionalExtensions = tmpView.UseExtensions.filter(ext => !addedExtensions.has(ext.fullyQualified));
await addSegments([{ 'used-extension': tmpView.UseExtensions.map(x => x.fullyQualified) }]);
if (additionalExtensions.length === 0) {
continue;
}
// acquire additional extensions
for (const additionalExtension of additionalExtensions) {
try {
addedExtensions.add(additionalExtension.fullyQualified);
if (await exists(localPath)) {
localPath = filePath(localPath);
if (messageFormat !== 'json' && messageFormat !== 'yaml') {
// local package
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Loading local AutoRest extension '${additionalExtension.name}' (${localPath})`
});
let ext = loadedExtensions[additionalExtension.fullyQualified];
// not yet loaded?
if (!ext) {
let localPath = untildify(additionalExtension.source);
// try resolving the package locally (useful for self-contained)
try {
const fileProbe = '/package.json';
localPath = require.resolve(additionalExtension.name + fileProbe); // have to resolve specific file - resolving a package by name will fail if no 'main' is present
localPath = localPath.slice(0, localPath.length - fileProbe.length);
} catch {
// no worries
}
const pack = await extMgr.findPackage(additionalExtension.name, localPath);
const extension = new LocalExtension(pack, localPath);
// start extension
ext = loadedExtensions[additionalExtension.fullyQualified] = {
extension,
autorestExtension: new LazyPromise(async () => AutoRestExtension.FromChildProcess(additionalExtension.name, await extension.start(enableDebugger)))
};
} else {
// remote package`
const installedExtension = await extMgr.getInstalledExtension(additionalExtension.name, additionalExtension.source);
if (installedExtension) {
// trim off the '@org' and 'autorest.' from the name.
const shortname = additionalExtension.name.split('/').last.replace(/^autorest\./ig, '');
const view = [...createView().GetNestedConfiguration(shortname)];
const enableDebugger = view.length > 0 ? <boolean>(view[0].GetEntry('debugger')) : false;
if (await exists(localPath)) {
localPath = filePath(localPath);
if (messageFormat !== 'json' && messageFormat !== 'yaml') {
// local package
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Loading AutoRest extension '${additionalExtension.name}' (${additionalExtension.source}->${installedExtension.version})`
Text: `> Loading local AutoRest extension '${additionalExtension.name}' (${localPath})`
});
}
// start extension
ext = loadedExtensions[additionalExtension.fullyQualified] = {
extension: installedExtension,
autorestExtension: new LazyPromise(async () => AutoRestExtension.FromChildProcess(additionalExtension.name, await installedExtension.start(enableDebugger)))
};
} else {
// acquire extension
const pack = await extMgr.findPackage(additionalExtension.name, additionalExtension.source);
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Installing AutoRest extension '${additionalExtension.name}' (${additionalExtension.source})`
});
const cwd = process.cwd(); // TODO: fix extension?
const extension = await extMgr.installPackage(pack, false, 5 * 60 * 1000, (progressInit: any) => progressInit.Message.Subscribe((s: any, m: any) => tmpView.Message({ Text: m, Channel: Channel.Verbose })));
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Installed AutoRest extension '${additionalExtension.name}' (${additionalExtension.source}->${extension.version})`
});
process.chdir(cwd);
// start extension
const pack = await extMgr.findPackage(additionalExtension.name, localPath);
const extension = new LocalExtension(pack, localPath);
// start extension
ext = loadedExtensions[additionalExtension.fullyQualified] = {
extension,
autorestExtension: new LazyPromise(async () => AutoRestExtension.FromChildProcess(additionalExtension.name, await extension.start(enableDebugger)))
};
} else {
// remote package`
const installedExtension = await extMgr.getInstalledExtension(additionalExtension.name, additionalExtension.source);
if (installedExtension) {
if (messageFormat !== 'json' && messageFormat !== 'yaml') {
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Loading AutoRest extension '${additionalExtension.name}' (${additionalExtension.source}->${installedExtension.version})`
});
}
// start extension
ext = loadedExtensions[additionalExtension.fullyQualified] = {
extension: installedExtension,
autorestExtension: new LazyPromise(async () => AutoRestExtension.FromChildProcess(additionalExtension.name, await installedExtension.start(enableDebugger)))
};
} else {
// acquire extension
const pack = await extMgr.findPackage(additionalExtension.name, additionalExtension.source);
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Installing AutoRest extension '${additionalExtension.name}' (${additionalExtension.source})`
});
const cwd = process.cwd(); // TODO: fix extension?
const extension = await extMgr.installPackage(pack, false, 5 * 60 * 1000, (progressInit: any) => progressInit.Message.Subscribe((s: any, m: any) => tmpView.Message({ Text: m, Channel: Channel.Verbose })));
messageEmitter.Message.Dispatch({
Channel: Channel.Information,
Text: `> Installed AutoRest extension '${additionalExtension.name}' (${additionalExtension.source}->${extension.version})`
});
process.chdir(cwd);
// start extension
ext = loadedExtensions[additionalExtension.fullyQualified] = {
extension,
autorestExtension: new LazyPromise(async () => AutoRestExtension.FromChildProcess(additionalExtension.name, await extension.start(enableDebugger)))
};
}
}
}
await includeFn(fsLocal);
// merge config from extension
const inputView = messageEmitter.DataStore.GetReadThroughScope(new RealFileSystem());
const cp = simplifyUri(CreateFileUri(await ext.extension.configurationPath));
messageEmitter.Message.Dispatch({
Channel: Channel.Verbose,
Text: `> Including extension configuration file '${cp}'`
});
const blocks = await this.ParseCodeBlocks(
await inputView.ReadStrict(cp),
createView(),
`extension-config-${additionalExtension.fullyQualified}`);
// even though we load extensions after the default configuration, I want them to be able to
// trigger changes in the default configuration loading (ie, an extension can set a flag to use a different pipeline.)
viewsToHandle.push(createView(await addSegments(blocks.map(each => each['pipeline-model'] ? ({ ...each, 'load-priority': 1000 }) : each))));
} catch (e) {
messageEmitter.Message.Dispatch({
Channel: Channel.Fatal,
Text: `Failed to install or start extension '${additionalExtension.name}' (${additionalExtension.source})`
});
throw e;
}
await includeFn(fsLocal);
// merge config from extension
const inputView = messageEmitter.DataStore.GetReadThroughScope(new RealFileSystem());
const cp = simplifyUri(CreateFileUri(await ext.extension.configurationPath));
messageEmitter.Message.Dispatch({
Channel: Channel.Verbose,
Text: `> Including extension configuration file '${cp}'`
});
const blocks = await this.ParseCodeBlocks(
await inputView.ReadStrict(cp),
createView(),
`extension-config-${additionalExtension.fullyQualified}`);
// even though we load extensions after the default configuration, I want them to be able to
// trigger changes in the default configuration loading (ie, an extension can set a flag to use a different pipeline.)
viewsToHandle.push(createView(await addSegments(blocks.map(each => each['pipeline-model'] ? ({ ...each, 'load-priority': 1000 }) : each))));
} catch (e) {
messageEmitter.Message.Dispatch({
Channel: Channel.Fatal,
Text: `Failed to install or start extension '${additionalExtension.name}' (${additionalExtension.source})`
});
throw e;
}
await includeFn(fsLocal);
}
// resolve any outstanding includes again
await includeFn(fsLocal);
}
await includeFn(fsLocal);
};
// resolve the extensions
await resolveExtensions();
// re-acquire CLI and configuration files at a lower priority
// this enables the configuration of a plugin to specify stuff like `pipeline-model`
// which would unlock a guarded section that has $(pipeline-model) == 'v3' in the yaml block.
@ -1032,8 +1038,11 @@ export class Configuration {
'config');
await addSegments(blocks, false);
await includeFn(this.fileSystem);
await resolveExtensions();
return createView([...configs, ...blocks, ...secondPass]).Indexer;
}
await resolveExtensions();
// return the final view
return createView().Indexer;
}
public static async DetectConfigurationFile(fileSystem: IFileSystem, configFileOrFolderUri: string | null, messageEmitter?: MessageEmitter, walkUpFolders = false): Promise<string | null> {

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

@ -95,6 +95,14 @@ async function parseCodeBlocksInternal(config: ConfigurationView, hLiterate: Dat
}
export function evaluateGuard(rawFenceGuard: string, contextObject: any): boolean {
// extend the context object so that we can have some helper functions.
contextObject = {
...contextObject,
/** finds out if there is an extension being loaded already by a given name */
isLoaded: (name: string) => contextObject['used-extension'] && !!(contextObject['used-extension'].find(each => each[0].startsWith(`"[\\"${name}\\"`)))
};
// trim the language from the front first
let match = /^\S*\s*(.*)/.exec(rawFenceGuard);
const fence = match && match[1];
@ -108,8 +116,9 @@ export function evaluateGuard(rawFenceGuard: string, contextObject: any): boolea
try {
if (!fence.includes('$(')) {
try {
return safeEval<boolean>(fence);
return safeEval<boolean>(fence, contextObject);
} catch (e) {
//console.log(`1 failed to eval ${fence}`);
return false;
}
}
@ -119,9 +128,10 @@ export function evaluateGuard(rawFenceGuard: string, contextObject: any): boolea
// Let's run it only if there are no unresolved values for now.
if (!expressionFence.includes('$(')) {
return safeEval<boolean>(expressionFence);
return safeEval<boolean>(expressionFence, contextObject);
}
} catch (E) {
// console.log(`2 failed to eval ${expressionFence}`);
// not a legal expression?
}
@ -135,9 +145,15 @@ export function evaluateGuard(rawFenceGuard: string, contextObject: any): boolea
// let's resolve them to undefined and see what happens.
try {
return safeEval<boolean>(expressionFence.replace(/\$\(.*?\)/g, 'undefined'));
return safeEval<boolean>(expressionFence.replace(/\$\(.*?\)/g, 'undefined'), contextObject);
} catch {
return safeEval<boolean>(fence.replace(/\$\(.*?\)/g, 'undefined'));
// console.log(`3 failed to eval ${expressionFence.replace(/\$\(.*?\)/g, 'undefined')}`);
try {
return safeEval<boolean>(fence.replace(/\$\(.*?\)/g, 'undefined'), contextObject);
} catch {
//console.log(`4 failed to eval ${fence.replace(/\$\(.*?\)/g, 'undefined')}`);
return false;
}
}
}

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

@ -9,8 +9,8 @@ try-require: ./readme.powershell.md
Note: if the --powershell is mentioned, but they are using autorest.powershell locally, don't try to load the autorest.powershell from npm.
``` yaml $(powershell) && ( "$(requesting-extensions)".indexOf('autorest.powershell') === -1 )
``` yaml $(powershell) && !isLoaded('@autorest/powershell')
# load the extension
use-extension:
"@microsoft.azure/autorest.powershell": "beta"
"@autorest/powershell": "beta"
```