Skip to content

Commit 00383b7

Browse files
authored
Merge pull request #2099 from cdr/open-in
Make opening in an existing instance work outside code-server
2 parents c6ba129 + d7e3112 commit 00383b7

File tree

8 files changed

+439
-234
lines changed

8 files changed

+439
-234
lines changed

ci/build/test-standalone-release.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ main() {
1515
./release-standalone/bin/code-server --extensions-dir "$EXTENSIONS_DIR" --install-extension ms-python.python
1616
local installed_extensions
1717
installed_extensions="$(./release-standalone/bin/code-server --extensions-dir "$EXTENSIONS_DIR" --list-extensions 2>&1)"
18-
if [[ $installed_extensions != *"info Using config file ~/.config/code-server/config.yaml
19-
ms-python.python" ]]; then
18+
if [[ $installed_extensions != "ms-python.python" ]]; then
2019
echo "Unexpected output from listing extensions:"
2120
echo "$installed_extensions"
2221
exit 1

ci/dev/vscode.patch

+25
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,31 @@ index b3c89e51cfc25a53293a352a2a8ad50d5f26d595..e21abe4e13bc25a5b72f556bbfb61085
30353035
registerSingleton(IExtHostTerminalService, ExtHostTerminalService);
30363036
registerSingleton(IExtHostTunnelService, ExtHostTunnelService);
30373037
+registerSingleton(IExtHostNodeProxy, class extends NotImplementedProxy<IExtHostNodeProxy>(String(IExtHostNodeProxy)) { whenReady = Promise.resolve(); });
3038+
diff --git a/src/vs/workbench/api/node/extHostCLIServer.ts b/src/vs/workbench/api/node/extHostCLIServer.ts
3039+
index 7cae126cc0f804273850933468690e0f9f10a5b8..08c2aa5cdae3f3d06bb08b7055dc7e7def260132 100644
3040+
--- a/src/vs/workbench/api/node/extHostCLIServer.ts
3041+
+++ b/src/vs/workbench/api/node/extHostCLIServer.ts
3042+
@@ -11,6 +11,8 @@ import { IWindowOpenable, IOpenWindowOptions } from 'vs/platform/windows/common/
3043+
import { URI } from 'vs/base/common/uri';
3044+
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
3045+
import { ILogService } from 'vs/platform/log/common/log';
3046+
+import { join } from 'vs/base/common/path';
3047+
+import { tmpdir } from 'os';
3048+
3049+
export interface OpenCommandPipeArgs {
3050+
type: 'open';
3051+
@@ -54,6 +56,11 @@ export class CLIServer {
3052+
private async setup(): Promise<string> {
3053+
this._ipcHandlePath = generateRandomPipeName();
3054+
3055+
+ // NOTE@coder: Write this out so we can get the most recent path.
3056+
+ fs.promises.writeFile(join(tmpdir(), "vscode-ipc"), this._ipcHandlePath).catch((error) => {
3057+
+ this.logService.error(error);
3058+
+ });
3059+
+
3060+
try {
3061+
this._server.listen(this.ipcHandlePath);
3062+
this._server.on('error', err => this.logService.error(err));
30383063
diff --git a/src/vs/workbench/api/worker/extHost.worker.services.ts b/src/vs/workbench/api/worker/extHost.worker.services.ts
30393064
index 3843fdec386edc09a1d361b63de892a04e0070ed..8aac4df527857e964798362a69f5591bef07c165 100644
30403065
--- a/src/vs/workbench/api/worker/extHost.worker.services.ts

src/node/cli.ts

+67-22
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as os from "os"
55
import * as path from "path"
66
import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc"
77
import { AuthType } from "./http"
8-
import { generatePassword, humanPath, paths } from "./util"
8+
import { canConnect, generatePassword, humanPath, paths } from "./util"
99

1010
export class Optional<T> {
1111
public constructor(public readonly value?: T) {}
@@ -152,12 +152,12 @@ const options: Options<Required<Args>> = {
152152
"new-window": {
153153
type: "boolean",
154154
short: "n",
155-
description: "Force to open a new window. (use with open-in)",
155+
description: "Force to open a new window.",
156156
},
157157
"reuse-window": {
158158
type: "boolean",
159159
short: "r",
160-
description: "Force to open a file or folder in an already opened window. (use with open-in)",
160+
description: "Force to open a file or folder in an already opened window.",
161161
},
162162

163163
locale: { type: "string" },
@@ -327,6 +327,21 @@ export const parse = (
327327

328328
logger.debug("parsed command line", field("args", args))
329329

330+
return args
331+
}
332+
333+
export async function setDefaults(args: Args): Promise<Args> {
334+
args = { ...args }
335+
336+
if (!args["user-data-dir"]) {
337+
await copyOldMacOSDataDir()
338+
args["user-data-dir"] = paths.data
339+
}
340+
341+
if (!args["extensions-dir"]) {
342+
args["extensions-dir"] = path.join(args["user-data-dir"], "extensions")
343+
}
344+
330345
// --verbose takes priority over --log and --log takes priority over the
331346
// environment variable.
332347
if (args.verbose) {
@@ -369,21 +384,6 @@ export const parse = (
369384
return args
370385
}
371386

372-
export async function setDefaults(args: Args): Promise<Args> {
373-
args = { ...args }
374-
375-
if (!args["user-data-dir"]) {
376-
await copyOldMacOSDataDir()
377-
args["user-data-dir"] = paths.data
378-
}
379-
380-
if (!args["extensions-dir"]) {
381-
args["extensions-dir"] = path.join(args["user-data-dir"], "extensions")
382-
}
383-
384-
return args
385-
}
386-
387387
async function defaultConfigFile(): Promise<string> {
388388
return `bind-addr: 127.0.0.1:8080
389389
auth: password
@@ -410,10 +410,6 @@ export async function readConfigFile(configPath?: string): Promise<Args> {
410410
logger.info(`Wrote default config file to ${humanPath(configPath)}`)
411411
}
412412

413-
if (!process.env.CODE_SERVER_PARENT_PID && !process.env.VSCODE_IPC_HOOK_CLI) {
414-
logger.info(`Using config file ${humanPath(configPath)}`)
415-
}
416-
417413
const configFile = await fs.readFile(configPath)
418414
const config = yaml.safeLoad(configFile.toString(), {
419415
filename: configPath,
@@ -496,3 +492,52 @@ async function copyOldMacOSDataDir(): Promise<void> {
496492
await fs.copy(oldDataDir, paths.data)
497493
}
498494
}
495+
496+
export const shouldRunVsCodeCli = (args: Args): boolean => {
497+
return !!args["list-extensions"] || !!args["install-extension"] || !!args["uninstall-extension"]
498+
}
499+
500+
/**
501+
* Determine if it looks like the user is trying to open a file or folder in an
502+
* existing instance. The arguments here should be the arguments the user
503+
* explicitly passed on the command line, not defaults or the configuration.
504+
*/
505+
export const shouldOpenInExistingInstance = async (args: Args): Promise<string | undefined> => {
506+
// Always use the existing instance if we're running from VS Code's terminal.
507+
if (process.env.VSCODE_IPC_HOOK_CLI) {
508+
return process.env.VSCODE_IPC_HOOK_CLI
509+
}
510+
511+
const readSocketPath = async (): Promise<string | undefined> => {
512+
try {
513+
return await fs.readFile(path.join(os.tmpdir(), "vscode-ipc"), "utf8")
514+
} catch (error) {
515+
if (error.code !== "ENOENT") {
516+
throw error
517+
}
518+
}
519+
return undefined
520+
}
521+
522+
// If these flags are set then assume the user is trying to open in an
523+
// existing instance since these flags have no effect otherwise.
524+
const openInFlagCount = ["reuse-window", "new-window"].reduce((prev, cur) => {
525+
return args[cur as keyof Args] ? prev + 1 : prev
526+
}, 0)
527+
if (openInFlagCount > 0) {
528+
return readSocketPath()
529+
}
530+
531+
// It's possible the user is trying to spawn another instance of code-server.
532+
// Check if any unrelated flags are set (check against one because `_` always
533+
// exists), that a file or directory was passed, and that the socket is
534+
// active.
535+
if (Object.keys(args).length === 1 && args._.length > 0) {
536+
const socketPath = await readSocketPath()
537+
if (socketPath && (await canConnect(socketPath))) {
538+
return socketPath
539+
}
540+
}
541+
542+
return undefined
543+
}

0 commit comments

Comments
 (0)