Enable access to vscode cli

This commit is contained in:
Asher 2020-02-18 12:24:12 -06:00
parent 0ec83f8736
commit 39a57700bc
No known key found for this signature in database
GPG Key ID: D63C1EF81242354A
4 changed files with 73 additions and 15 deletions

View File

@ -12,7 +12,7 @@ index 160c42ed74..0d544c495c 100644
coverage/ coverage/
diff --git a/coder.js b/coder.js diff --git a/coder.js b/coder.js
new file mode 100644 new file mode 100644
index 0000000000..fc18355f89 index 0000000000..6aee0e46bc
--- /dev/null --- /dev/null
+++ b/coder.js +++ b/coder.js
@@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
@ -32,9 +32,9 @@ index 0000000000..fc18355f89
+ buildfile.workbenchWeb, + buildfile.workbenchWeb,
+ buildfile.workerExtensionHost, + buildfile.workerExtensionHost,
+ buildfile.keyboardMaps, + buildfile.keyboardMaps,
+ buildfile.entrypoint('vs/platform/files/node/watcher/unix/watcherApp', ["vs/css", "vs/nls"]), + buildfile.entrypoint("vs/platform/files/node/watcher/unix/watcherApp", ["vs/css", "vs/nls"]),
+ buildfile.entrypoint('vs/platform/files/node/watcher/nsfw/watcherApp', ["vs/css", "vs/nls"]), + buildfile.entrypoint("vs/platform/files/node/watcher/nsfw/watcherApp", ["vs/css", "vs/nls"]),
+ buildfile.entrypoint('vs/workbench/services/extensions/node/extensionHostProcess', ["vs/css", "vs/nls"]), + buildfile.entrypoint("vs/workbench/services/extensions/node/extensionHostProcess", ["vs/css", "vs/nls"]),
+]); +]);
+ +
+const vscodeResources = [ +const vscodeResources = [
@ -894,10 +894,10 @@ index 0000000000..eb62b87798
+} +}
diff --git a/src/vs/server/entry.ts b/src/vs/server/entry.ts diff --git a/src/vs/server/entry.ts b/src/vs/server/entry.ts
new file mode 100644 new file mode 100644
index 0000000000..9995e9f7fc index 0000000000..0d7feaa24e
--- /dev/null --- /dev/null
+++ b/src/vs/server/entry.ts +++ b/src/vs/server/entry.ts
@@ -0,0 +1,67 @@ @@ -0,0 +1,76 @@
+import { field } from '@coder/logger'; +import { field } from '@coder/logger';
+import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; +import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
+import { CodeServerMessage, VscodeMessage } from 'vs/server/ipc'; +import { CodeServerMessage, VscodeMessage } from 'vs/server/ipc';
@ -953,6 +953,15 @@ index 0000000000..9995e9f7fc
+ exit(1); + exit(1);
+ } + }
+ break; + break;
+ case 'cli':
+ try {
+ await vscode.cli(message.args);
+ exit(0);
+ } catch (error) {
+ logger.error(error.message);
+ exit(1);
+ }
+ break;
+ case 'socket': + case 'socket':
+ vscode.handleWebSocket(socket, message.query); + vscode.handleWebSocket(socket, message.query);
+ break; + break;
@ -976,10 +985,10 @@ index 0000000000..56331ff1fc
+require('../../bootstrap-amd').load('vs/server/entry'); +require('../../bootstrap-amd').load('vs/server/entry');
diff --git a/src/vs/server/ipc.d.ts b/src/vs/server/ipc.d.ts diff --git a/src/vs/server/ipc.d.ts b/src/vs/server/ipc.d.ts
new file mode 100644 new file mode 100644
index 0000000000..a1047fff86 index 0000000000..82566066ff
--- /dev/null --- /dev/null
+++ b/src/vs/server/ipc.d.ts +++ b/src/vs/server/ipc.d.ts
@@ -0,0 +1,101 @@ @@ -0,0 +1,106 @@
+/** +/**
+ * External interfaces for integration into code-server over IPC. No vs imports + * External interfaces for integration into code-server over IPC. No vs imports
+ * should be made in this file. + * should be made in this file.
@ -998,7 +1007,12 @@ index 0000000000..a1047fff86
+ query: Query; + query: Query;
+} +}
+ +
+export type CodeServerMessage = InitMessage | SocketMessage; +export interface CliMessage {
+ type: 'cli';
+ args: Args;
+}
+
+export type CodeServerMessage = InitMessage | SocketMessage | CliMessage;
+ +
+export interface ReadyMessage { +export interface ReadyMessage {
+ type: 'ready'; + type: 'ready';
@ -1032,8 +1046,8 @@ index 0000000000..a1047fff86
+} +}
+ +
+export interface VscodeOptions { +export interface VscodeOptions {
+ readonly remoteAuthority: string;
+ readonly args: Args; + readonly args: Args;
+ readonly remoteAuthority: string;
+ readonly startPath?: StartPath; + readonly startPath?: StartPath;
+} +}
+ +
@ -2152,10 +2166,10 @@ index 0000000000..3c74512192
+} +}
diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts
new file mode 100644 new file mode 100644
index 0000000000..13d71949ce index 0000000000..20dbca69b2
--- /dev/null --- /dev/null
+++ b/src/vs/server/node/server.ts +++ b/src/vs/server/node/server.ts
@@ -0,0 +1,252 @@ @@ -0,0 +1,257 @@
+import * as net from 'net'; +import * as net from 'net';
+import * as path from 'path'; +import * as path from 'path';
+import { Emitter } from 'vs/base/common/event'; +import { Emitter } from 'vs/base/common/event';
@ -2165,6 +2179,7 @@ index 0000000000..13d71949ce
+import { ClientConnectionEvent, IPCServer, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; +import { ClientConnectionEvent, IPCServer, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
+import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc'; +import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc';
+import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; +import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
+import { main } from "vs/code/node/cliProcessMain";
+import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; +import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
+import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; +import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
@ -2222,6 +2237,10 @@ index 0000000000..13d71949ce
+ private readonly services = new ServiceCollection(); + private readonly services = new ServiceCollection();
+ private servicesPromise?: Promise<void>; + private servicesPromise?: Promise<void>;
+ +
+ public async cli(args: ParsedArgs): Promise<void> {
+ return main(args);
+ }
+
+ public async initialize(options: VscodeOptions): Promise<WorkbenchOptions> { + public async initialize(options: VscodeOptions): Promise<WorkbenchOptions> {
+ const transformer = getUriTransformer(options.remoteAuthority); + const transformer = getUriTransformer(options.remoteAuthority);
+ if (!this.servicesPromise) { + if (!this.servicesPromise) {

View File

@ -136,7 +136,7 @@ export class MainHttpProvider extends HttpProvider {
private async getUpdate(): Promise<string> { private async getUpdate(): Promise<string> {
if (!this.update.enabled) { if (!this.update.enabled) {
return "Updates are disabled" return `<div class="block-row"><div class="item"><div class="sub">Updates are disabled</div></div></div>`
} }
const humanize = (time: number): string => { const humanize = (time: number): string => {

View File

@ -15,6 +15,7 @@ export interface Args extends VsArgs {
readonly cert?: OptionalString readonly cert?: OptionalString
readonly "cert-key"?: string readonly "cert-key"?: string
readonly "disable-updates"?: boolean readonly "disable-updates"?: boolean
readonly "disable-telemetry"?: boolean
readonly help?: boolean readonly help?: boolean
readonly host?: string readonly host?: string
readonly json?: boolean readonly json?: boolean
@ -22,6 +23,9 @@ export interface Args extends VsArgs {
readonly port?: number readonly port?: number
readonly socket?: string readonly socket?: string
readonly version?: boolean readonly version?: boolean
readonly "list-extensions"?: boolean
readonly "install-extension"?: string[]
readonly "uninstall-extension"?: string[]
readonly _: string[] readonly _: string[]
} }
@ -68,6 +72,7 @@ const options: Options<Required<Args>> = {
}, },
"cert-key": { type: "string", path: true, description: "Path to certificate key when using non-generated cert." }, "cert-key": { type: "string", path: true, description: "Path to certificate key when using non-generated cert." },
"disable-updates": { type: "boolean", description: "Disable automatic updates." }, "disable-updates": { type: "boolean", description: "Disable automatic updates." },
"disable-telemetry": { type: "boolean", description: "Disable telemetry." },
host: { type: "string", description: "Host for the HTTP server." }, host: { type: "string", description: "Host for the HTTP server." },
help: { type: "boolean", short: "h", description: "Show this output." }, help: { type: "boolean", short: "h", description: "Show this output." },
json: { type: "boolean" }, json: { type: "boolean" },
@ -82,6 +87,9 @@ const options: Options<Required<Args>> = {
"builtin-extensions-dir": { type: "string", path: true }, "builtin-extensions-dir": { type: "string", path: true },
"extra-extensions-dir": { type: "string[]", path: true }, "extra-extensions-dir": { type: "string[]", path: true },
"extra-builtin-extensions-dir": { type: "string[]", path: true }, "extra-builtin-extensions-dir": { type: "string[]", path: true },
"list-extensions": { type: "boolean" },
"install-extension": { type: "string[]" },
"uninstall-extension": { type: "string[]" },
log: { type: "string" }, log: { type: "string" },
verbose: { type: "boolean", short: "vvv", description: "Enable verbose logging." }, verbose: { type: "boolean", short: "vvv", description: "Enable verbose logging." },
@ -193,8 +201,13 @@ export const parse = (argv: string[]): Args => {
if (process.env.LOG_LEVEL === "trace" || args.verbose) { if (process.env.LOG_LEVEL === "trace" || args.verbose) {
args.verbose = true args.verbose = true
args.log = "trace" args.log = "trace"
} else if (!args.log) {
args.log = process.env.LOG_LEVEL
} }
// Ensure this passes down to forked processes.
process.env.LOG_LEVEL = args.log
switch (args.log) { switch (args.log) {
case "trace": case "trace":
logger.level = Level.Trace logger.level = Level.Trace

View File

@ -1,10 +1,13 @@
import { logger } from "@coder/logger" import { field, logger } from "@coder/logger"
import { Args, optionDescriptions, parse } from "./cli" import * as cp from "child_process"
import * as path from "path"
import { CliMessage } from "../../lib/vscode/src/vs/server/ipc"
import { ApiHttpProvider } from "./app/api" import { ApiHttpProvider } from "./app/api"
import { MainHttpProvider } from "./app/app" import { MainHttpProvider } from "./app/app"
import { LoginHttpProvider } from "./app/login" import { LoginHttpProvider } from "./app/login"
import { UpdateHttpProvider } from "./app/update" import { UpdateHttpProvider } from "./app/update"
import { VscodeHttpProvider } from "./app/vscode" import { VscodeHttpProvider } from "./app/vscode"
import { Args, optionDescriptions, parse } from "./cli"
import { AuthType, HttpServer } from "./http" import { AuthType, HttpServer } from "./http"
import { generateCertificate, generatePassword, hash, open } from "./util" import { generateCertificate, generatePassword, hash, open } from "./util"
import { ipcMain, wrap } from "./wrapper" import { ipcMain, wrap } from "./wrapper"
@ -105,6 +108,29 @@ if (args.help) {
console.log(version) console.log(version)
} }
process.exit(0) process.exit(0)
} else if (args["list-extensions"] || args["install-extension"] || args["uninstall-extension"]) {
process.env.NBIN_BYPASS = "true"
logger.debug("Forking VS Code CLI...")
const vscode = cp.fork(path.resolve(__dirname, "../../lib/vscode/out/vs/server/fork"), [], {
env: {
...process.env,
CODE_SERVER_PARENT_PID: process.pid.toString(),
},
})
vscode.once("message", (message) => {
logger.debug("Got message from VS Code", field("message", message))
if (message.type !== "ready") {
logger.error("Unexpected response waiting for ready response")
process.exit(1)
}
const send: CliMessage = { type: "cli", args }
vscode.send(send)
})
vscode.once("error", (error) => {
logger.error(error.message)
process.exit(1)
})
vscode.on("exit", (code) => process.exit(code || 0))
} else { } else {
wrap(() => main(args)) wrap(() => main(args))
} }