Skip to content

Commit 39a5770

Browse files
committed
Enable access to vscode cli
1 parent 0ec83f8 commit 39a5770

File tree

4 files changed

+73
-15
lines changed

4 files changed

+73
-15
lines changed

scripts/vscode.patch

+31-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ index 160c42ed74..0d544c495c 100644
1212
coverage/
1313
diff --git a/coder.js b/coder.js
1414
new file mode 100644
15-
index 0000000000..fc18355f89
15+
index 0000000000..6aee0e46bc
1616
--- /dev/null
1717
+++ b/coder.js
1818
@@ -0,0 +1,70 @@
@@ -32,9 +32,9 @@ index 0000000000..fc18355f89
3232
+ buildfile.workbenchWeb,
3333
+ buildfile.workerExtensionHost,
3434
+ buildfile.keyboardMaps,
35-
+ buildfile.entrypoint('vs/platform/files/node/watcher/unix/watcherApp', ["vs/css", "vs/nls"]),
36-
+ buildfile.entrypoint('vs/platform/files/node/watcher/nsfw/watcherApp', ["vs/css", "vs/nls"]),
37-
+ buildfile.entrypoint('vs/workbench/services/extensions/node/extensionHostProcess', ["vs/css", "vs/nls"]),
35+
+ buildfile.entrypoint("vs/platform/files/node/watcher/unix/watcherApp", ["vs/css", "vs/nls"]),
36+
+ buildfile.entrypoint("vs/platform/files/node/watcher/nsfw/watcherApp", ["vs/css", "vs/nls"]),
37+
+ buildfile.entrypoint("vs/workbench/services/extensions/node/extensionHostProcess", ["vs/css", "vs/nls"]),
3838
+]);
3939
+
4040
+const vscodeResources = [
@@ -894,10 +894,10 @@ index 0000000000..eb62b87798
894894
+}
895895
diff --git a/src/vs/server/entry.ts b/src/vs/server/entry.ts
896896
new file mode 100644
897-
index 0000000000..9995e9f7fc
897+
index 0000000000..0d7feaa24e
898898
--- /dev/null
899899
+++ b/src/vs/server/entry.ts
900-
@@ -0,0 +1,67 @@
900+
@@ -0,0 +1,76 @@
901901
+import { field } from '@coder/logger';
902902
+import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
903903
+import { CodeServerMessage, VscodeMessage } from 'vs/server/ipc';
@@ -953,6 +953,15 @@ index 0000000000..9995e9f7fc
953953
+ exit(1);
954954
+ }
955955
+ break;
956+
+ case 'cli':
957+
+ try {
958+
+ await vscode.cli(message.args);
959+
+ exit(0);
960+
+ } catch (error) {
961+
+ logger.error(error.message);
962+
+ exit(1);
963+
+ }
964+
+ break;
956965
+ case 'socket':
957966
+ vscode.handleWebSocket(socket, message.query);
958967
+ break;
@@ -976,10 +985,10 @@ index 0000000000..56331ff1fc
976985
+require('../../bootstrap-amd').load('vs/server/entry');
977986
diff --git a/src/vs/server/ipc.d.ts b/src/vs/server/ipc.d.ts
978987
new file mode 100644
979-
index 0000000000..a1047fff86
988+
index 0000000000..82566066ff
980989
--- /dev/null
981990
+++ b/src/vs/server/ipc.d.ts
982-
@@ -0,0 +1,101 @@
991+
@@ -0,0 +1,106 @@
983992
+/**
984993
+ * External interfaces for integration into code-server over IPC. No vs imports
985994
+ * should be made in this file.
@@ -998,7 +1007,12 @@ index 0000000000..a1047fff86
9981007
+ query: Query;
9991008
+}
10001009
+
1001-
+export type CodeServerMessage = InitMessage | SocketMessage;
1010+
+export interface CliMessage {
1011+
+ type: 'cli';
1012+
+ args: Args;
1013+
+}
1014+
+
1015+
+export type CodeServerMessage = InitMessage | SocketMessage | CliMessage;
10021016
+
10031017
+export interface ReadyMessage {
10041018
+ type: 'ready';
@@ -1032,8 +1046,8 @@ index 0000000000..a1047fff86
10321046
+}
10331047
+
10341048
+export interface VscodeOptions {
1035-
+ readonly remoteAuthority: string;
10361049
+ readonly args: Args;
1050+
+ readonly remoteAuthority: string;
10371051
+ readonly startPath?: StartPath;
10381052
+}
10391053
+
@@ -2152,10 +2166,10 @@ index 0000000000..3c74512192
21522166
+}
21532167
diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts
21542168
new file mode 100644
2155-
index 0000000000..13d71949ce
2169+
index 0000000000..20dbca69b2
21562170
--- /dev/null
21572171
+++ b/src/vs/server/node/server.ts
2158-
@@ -0,0 +1,252 @@
2172+
@@ -0,0 +1,257 @@
21592173
+import * as net from 'net';
21602174
+import * as path from 'path';
21612175
+import { Emitter } from 'vs/base/common/event';
@@ -2165,6 +2179,7 @@ index 0000000000..13d71949ce
21652179
+import { ClientConnectionEvent, IPCServer, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
21662180
+import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc';
21672181
+import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
2182+
+import { main } from "vs/code/node/cliProcessMain";
21682183
+import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
21692184
+import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
21702185
+import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
@@ -2222,6 +2237,10 @@ index 0000000000..13d71949ce
22222237
+ private readonly services = new ServiceCollection();
22232238
+ private servicesPromise?: Promise<void>;
22242239
+
2240+
+ public async cli(args: ParsedArgs): Promise<void> {
2241+
+ return main(args);
2242+
+ }
2243+
+
22252244
+ public async initialize(options: VscodeOptions): Promise<WorkbenchOptions> {
22262245
+ const transformer = getUriTransformer(options.remoteAuthority);
22272246
+ if (!this.servicesPromise) {

src/node/app/app.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export class MainHttpProvider extends HttpProvider {
136136

137137
private async getUpdate(): Promise<string> {
138138
if (!this.update.enabled) {
139-
return "Updates are disabled"
139+
return `<div class="block-row"><div class="item"><div class="sub">Updates are disabled</div></div></div>`
140140
}
141141

142142
const humanize = (time: number): string => {

src/node/cli.ts

+13
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@ export interface Args extends VsArgs {
1515
readonly cert?: OptionalString
1616
readonly "cert-key"?: string
1717
readonly "disable-updates"?: boolean
18+
readonly "disable-telemetry"?: boolean
1819
readonly help?: boolean
1920
readonly host?: string
2021
readonly json?: boolean
2122
readonly open?: boolean
2223
readonly port?: number
2324
readonly socket?: string
2425
readonly version?: boolean
26+
readonly "list-extensions"?: boolean
27+
readonly "install-extension"?: string[]
28+
readonly "uninstall-extension"?: string[]
2529
readonly _: string[]
2630
}
2731

@@ -68,6 +72,7 @@ const options: Options<Required<Args>> = {
6872
},
6973
"cert-key": { type: "string", path: true, description: "Path to certificate key when using non-generated cert." },
7074
"disable-updates": { type: "boolean", description: "Disable automatic updates." },
75+
"disable-telemetry": { type: "boolean", description: "Disable telemetry." },
7176
host: { type: "string", description: "Host for the HTTP server." },
7277
help: { type: "boolean", short: "h", description: "Show this output." },
7378
json: { type: "boolean" },
@@ -82,6 +87,9 @@ const options: Options<Required<Args>> = {
8287
"builtin-extensions-dir": { type: "string", path: true },
8388
"extra-extensions-dir": { type: "string[]", path: true },
8489
"extra-builtin-extensions-dir": { type: "string[]", path: true },
90+
"list-extensions": { type: "boolean" },
91+
"install-extension": { type: "string[]" },
92+
"uninstall-extension": { type: "string[]" },
8593

8694
log: { type: "string" },
8795
verbose: { type: "boolean", short: "vvv", description: "Enable verbose logging." },
@@ -193,8 +201,13 @@ export const parse = (argv: string[]): Args => {
193201
if (process.env.LOG_LEVEL === "trace" || args.verbose) {
194202
args.verbose = true
195203
args.log = "trace"
204+
} else if (!args.log) {
205+
args.log = process.env.LOG_LEVEL
196206
}
197207

208+
// Ensure this passes down to forked processes.
209+
process.env.LOG_LEVEL = args.log
210+
198211
switch (args.log) {
199212
case "trace":
200213
logger.level = Level.Trace

src/node/entry.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { logger } from "@coder/logger"
2-
import { Args, optionDescriptions, parse } from "./cli"
1+
import { field, logger } from "@coder/logger"
2+
import * as cp from "child_process"
3+
import * as path from "path"
4+
import { CliMessage } from "../../lib/vscode/src/vs/server/ipc"
35
import { ApiHttpProvider } from "./app/api"
46
import { MainHttpProvider } from "./app/app"
57
import { LoginHttpProvider } from "./app/login"
68
import { UpdateHttpProvider } from "./app/update"
79
import { VscodeHttpProvider } from "./app/vscode"
10+
import { Args, optionDescriptions, parse } from "./cli"
811
import { AuthType, HttpServer } from "./http"
912
import { generateCertificate, generatePassword, hash, open } from "./util"
1013
import { ipcMain, wrap } from "./wrapper"
@@ -105,6 +108,29 @@ if (args.help) {
105108
console.log(version)
106109
}
107110
process.exit(0)
111+
} else if (args["list-extensions"] || args["install-extension"] || args["uninstall-extension"]) {
112+
process.env.NBIN_BYPASS = "true"
113+
logger.debug("Forking VS Code CLI...")
114+
const vscode = cp.fork(path.resolve(__dirname, "../../lib/vscode/out/vs/server/fork"), [], {
115+
env: {
116+
...process.env,
117+
CODE_SERVER_PARENT_PID: process.pid.toString(),
118+
},
119+
})
120+
vscode.once("message", (message) => {
121+
logger.debug("Got message from VS Code", field("message", message))
122+
if (message.type !== "ready") {
123+
logger.error("Unexpected response waiting for ready response")
124+
process.exit(1)
125+
}
126+
const send: CliMessage = { type: "cli", args }
127+
vscode.send(send)
128+
})
129+
vscode.once("error", (error) => {
130+
logger.error(error.message)
131+
process.exit(1)
132+
})
133+
vscode.on("exit", (code) => process.exit(code || 0))
108134
} else {
109135
wrap(() => main(args))
110136
}

0 commit comments

Comments
 (0)