forked from microsoft/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ec805db
commit 38db177
Showing
3 changed files
with
228 additions
and
194 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,207 +1,127 @@ | ||
"use strict"; | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
const fs = require('fs').promises; | ||
const path = require('path'); | ||
const cp = require('child_process'); | ||
const os = require('os'); | ||
const mkdirp = require('mkdirp'); | ||
const product = require('../product.json'); | ||
const root = path.resolve(path.join(__dirname, '..', '..')); | ||
const exists = (path) => fs.stat(path).then(() => true, () => false); | ||
|
||
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json'); | ||
|
||
async function readControlFile() { | ||
try { | ||
return JSON.parse(await fs.readFile(controlFilePath, 'utf8')); | ||
} catch (err) { | ||
return {}; | ||
} | ||
} | ||
|
||
async function writeControlFile(control) { | ||
await mkdirp(path.dirname(controlFilePath)); | ||
await fs.writeFile(controlFilePath, JSON.stringify(control, null, ' ')); | ||
} | ||
|
||
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } | ||
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var g = generator.apply(thisArg, _arguments || []), i, q = []; | ||
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; | ||
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } | ||
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } | ||
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } | ||
function fulfill(value) { resume("next", value); } | ||
function reject(value) { resume("throw", value); } | ||
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } | ||
}; | ||
var __asyncValues = (this && this.__asyncValues) || function (o) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var m = o[Symbol.asyncIterator], i; | ||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const fs_1 = require("fs"); | ||
const path = require("path"); | ||
const cp = require("child_process"); | ||
const commander_1 = require("commander"); | ||
const root = path.resolve(path.join(__dirname, '..')); | ||
var ExtensionType; | ||
(function (ExtensionType) { | ||
ExtensionType["Grammar"] = "grammar"; | ||
ExtensionType["Theme"] = "theme"; | ||
ExtensionType["Misc"] = "misc"; | ||
})(ExtensionType || (ExtensionType = {})); | ||
// const exists = (path) => fs.stat(path).then(() => true, () => false); | ||
// const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json'); | ||
// async function readControlFile() { | ||
// try { | ||
// return JSON.parse(await fs.readFile(controlFilePath, 'utf8')); | ||
// } catch (err) { | ||
// return {}; | ||
// } | ||
// } | ||
// async function writeControlFile(control) { | ||
// await mkdirp(path.dirname(controlFilePath)); | ||
// await fs.writeFile(controlFilePath, JSON.stringify(control, null, ' ')); | ||
// } | ||
async function exec(cmd, args, opts = {}) { | ||
return new Promise((c, e) => { | ||
const child = cp.spawn(cmd, args, { stdio: 'inherit', env: process.env, ...opts }); | ||
child.on('close', code => code === 0 ? c() : e(`Returned ${code}`)); | ||
}); | ||
} | ||
|
||
function getFolderPath(extDesc) { | ||
const folder = extDesc.repo.replace(/.*\//, ''); | ||
return folderPath = path.join(root, folder); | ||
} | ||
|
||
async function getExtensionType(folderPath) { | ||
const pkg = JSON.parse(await fs.readFile(path.join(folderPath, 'package.json'), 'utf8')); | ||
|
||
if (pkg['contributes']['themes'] || pkg['contributes']['iconThemes']) { | ||
return 'theme'; | ||
} else if (pkg['contributes']['grammars']) { | ||
return 'grammar'; | ||
} else { | ||
return 'misc'; | ||
} | ||
return new Promise((c, e) => { | ||
const child = cp.spawn(cmd, args, Object.assign({ stdio: 'inherit', env: process.env }, opts)); | ||
child.on('close', code => code === 0 ? c() : e(`Returned ${code}`)); | ||
}); | ||
} | ||
|
||
async function initExtension(extDesc) { | ||
const folderPath = getFolderPath(extDesc); | ||
|
||
if (!await exists(folderPath)) { | ||
console.log(`⏳ git clone: ${extDesc.name}`); | ||
await exec('git', ['clone', `${extDesc.repo}.git`], { cwd: root }); | ||
} | ||
|
||
const type = await getExtensionType(folderPath); | ||
return { path: folderPath, type, ...extDesc }; | ||
function getExtensionType(packageJson) { | ||
var _a, _b, _c; | ||
if (((_a = packageJson.contributes) === null || _a === void 0 ? void 0 : _a.themes) || ((_b = packageJson.contributes) === null || _b === void 0 ? void 0 : _b.iconThemes)) { | ||
return "theme" /* Theme */; | ||
} | ||
else if ((_c = packageJson.contributes) === null || _c === void 0 ? void 0 : _c.grammars) { | ||
return "grammar" /* Grammar */; | ||
} | ||
else { | ||
return "misc" /* Misc */; | ||
} | ||
} | ||
|
||
async function createWorkspace(type, extensions) { | ||
const workspaceName = `vscode-${type}-extensions.code-workspace`; | ||
const workspacePath = path.join(root, workspaceName); | ||
const workspace = { folders: extensions.map(ext => ({ path: path.basename(ext.path) })) }; | ||
|
||
if (!await exists(workspacePath)) { | ||
console.log(`✅ create workspace: ${workspaceName}`); | ||
} | ||
|
||
await fs.writeFile(workspacePath, JSON.stringify(workspace, undefined, ' ')); | ||
async function getExtension(extensionPath) { | ||
const packageJsonPath = path.join(extensionPath, 'package.json'); | ||
const packageJson = JSON.parse(await fs_1.promises.readFile(packageJsonPath, 'utf8')); | ||
const type = getExtensionType(packageJson); | ||
return { | ||
name: packageJson.name, | ||
path: extensionPath, | ||
type | ||
}; | ||
} | ||
|
||
async function init() { | ||
const extensions = []; | ||
|
||
for (const extDesc of product.builtInExtensions) { | ||
extensions.push(await initExtension(extDesc)); | ||
} | ||
|
||
await createWorkspace('all', extensions); | ||
|
||
const byType = extensions | ||
.reduce((m, e) => m.set(e.type, [...(m.get(e.type) || []), e]), new Map()); | ||
|
||
for (const [type, extensions] of byType) { | ||
await createWorkspace(type, extensions); | ||
} | ||
|
||
return byType; | ||
function getExtensions() { | ||
return __asyncGenerator(this, arguments, function* getExtensions_1() { | ||
const extensionsPath = path.join(root, 'extensions'); | ||
const children = yield __await(fs_1.promises.readdir(extensionsPath)); | ||
for (const child of children) { | ||
try { | ||
yield yield __await(yield __await(getExtension(path.join(extensionsPath, child)))); | ||
} | ||
catch (err) { | ||
if (/ENOENT|ENOTDIR/.test(err.message)) { | ||
continue; | ||
} | ||
throw err; | ||
} | ||
} | ||
}); | ||
} | ||
|
||
async function status() { | ||
const byType = await init(); | ||
const control = await readControlFile(); | ||
|
||
for (const [type, extensions] of byType) { | ||
console.log(`${type} (${extensions.length} extensions):`); | ||
|
||
const maxWidth = Math.max(...extensions.map(e => e.name.length)); | ||
for (const ext of extensions) { | ||
console.log(` ${ext.name.padEnd(maxWidth, ' ')} ➡ ${control[ext.name]}`); | ||
} | ||
} | ||
|
||
console.log(`total: ${product.builtInExtensions.length} extensions`); | ||
} | ||
|
||
async function each([cmd, ...args], opts) { | ||
await init(); | ||
|
||
for (const extDesc of product.builtInExtensions) { | ||
const folderPath = getFolderPath(extDesc); | ||
|
||
if (opts.type) { | ||
const type = await getExtensionType(folderPath); | ||
|
||
if (type !== opts.type) { | ||
continue; | ||
} | ||
} | ||
|
||
console.log(`👉 ${extDesc.name}`); | ||
await exec(cmd, args, { cwd: folderPath }); | ||
} | ||
} | ||
|
||
async function _link(extensions, opts, fn) { | ||
await init(); | ||
|
||
const control = await readControlFile(); | ||
|
||
for (const extDesc of product.builtInExtensions) { | ||
if (extensions.length > 0 && extensions.indexOf(extDesc.name) === -1) { | ||
continue; | ||
} | ||
|
||
if (opts.type) { | ||
const folderPath = getFolderPath(extDesc); | ||
const type = await getExtensionType(folderPath); | ||
|
||
if (type !== opts.type) { | ||
continue; | ||
} | ||
} | ||
|
||
await fn(control, extDesc); | ||
} | ||
|
||
await writeControlFile(control); | ||
} | ||
|
||
async function link(extensions, opts) { | ||
await _link(extensions, opts, async (control, extDesc) => { | ||
const ext = await initExtension(extDesc); | ||
control[extDesc.name] = ext.path; | ||
console.log(`👉 link: ${extDesc.name} ➡ ${ext.path}`); | ||
}); | ||
} | ||
|
||
async function unlink(extensions, opts) { | ||
await _link(extensions, opts, async (control, extDesc) => { | ||
control[extDesc.name] = 'marketplace'; | ||
console.log(`👉 unlink: ${extDesc.name}`); | ||
}); | ||
var e_1, _a; | ||
try { | ||
for (var _b = __asyncValues(getExtensions()), _c; _c = await _b.next(), !_c.done;) { | ||
const extension = _c.value; | ||
if (opts.type && extension.type !== opts.type) { | ||
continue; | ||
} | ||
console.log(`👉 ${extension.name}`); | ||
await exec(cmd, args, { cwd: extension.path }); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) await _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
|
||
if (require.main === module) { | ||
const { program } = require('commander'); | ||
|
||
program.version('0.0.1'); | ||
|
||
program | ||
.command('init') | ||
.description('Initialize workspace with built-in extensions') | ||
.action(init); | ||
|
||
program | ||
.command('status') | ||
.description('Print extension status') | ||
.action(status); | ||
|
||
program | ||
.command('each <command...>') | ||
.option('-t, --type <type>', 'Specific type only') | ||
.description('Run a command in each extension repository') | ||
.allowUnknownOption() | ||
.action(each); | ||
|
||
program | ||
.command('link [extensions...]') | ||
.option('-t, --type <type>', 'Specific type only') | ||
.description('Link with code-oss') | ||
.action(link); | ||
|
||
program | ||
.command('unlink [extensions...]') | ||
.option('-t, --type <type>', 'Specific type only') | ||
.description('Unlink from code-oss') | ||
.action(unlink); | ||
|
||
program.parseAsync(process.argv); | ||
commander_1.program.version('0.0.1'); | ||
commander_1.program | ||
.command('each <command...>') | ||
.option('-t, --type <type>', 'Specific type only') | ||
.description('Run a command in each extension repository') | ||
.allowUnknownOption() | ||
.action(each); | ||
commander_1.program.parseAsync(process.argv).catch(err => { | ||
console.error(err); | ||
process.exit(1); | ||
}); | ||
} |
Oops, something went wrong.