Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
myhjmzy
code-server
提交
fe19391c
C
code-server
项目概览
myhjmzy
/
code-server
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
code-server
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
fe19391c
编写于
9月 15, 2020
作者:
A
Asher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Read most recent socket path from file
上级
021c084e
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
156 addition
and
18 deletion
+156
-18
ci/dev/vscode.patch
ci/dev/vscode.patch
+25
-0
src/node/cli.ts
src/node/cli.ts
+30
-2
src/node/socket.ts
src/node/socket.ts
+1
-12
src/node/util.ts
src/node/util.ts
+15
-0
test/cli.test.ts
test/cli.test.ts
+85
-4
未找到文件。
ci/dev/vscode.patch
浏览文件 @
fe19391c
...
...
@@ -3035,6 +3035,31 @@ index b3c89e51cfc25a53293a352a2a8ad50d5f26d595..e21abe4e13bc25a5b72f556bbfb61085
registerSingleton(IExtHostTerminalService, ExtHostTerminalService);
registerSingleton(IExtHostTunnelService, ExtHostTunnelService);
+registerSingleton(IExtHostNodeProxy, class extends NotImplementedProxy<IExtHostNodeProxy>(String(IExtHostNodeProxy)) { whenReady = Promise.resolve(); });
diff --git a/src/vs/workbench/api/node/extHostCLIServer.ts b/src/vs/workbench/api/node/extHostCLIServer.ts
index 7cae126cc0f804273850933468690e0f9f10a5b8..08c2aa5cdae3f3d06bb08b7055dc7e7def260132 100644
--- a/src/vs/workbench/api/node/extHostCLIServer.ts
+++ b/src/vs/workbench/api/node/extHostCLIServer.ts
@@ -11,6 +11,8 @@
import { IWindowOpenable, IOpenWindowOptions } from 'vs/platform/windows/common/
import { URI } from 'vs/base/common/uri';
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { ILogService } from 'vs/platform/log/common/log';
+import { join } from 'vs/base/common/path';
+import { tmpdir } from 'os';
export interface OpenCommandPipeArgs {
type: 'open';
@@ -54,6 +56,11 @@
export class CLIServer {
private async setup(): Promise<string> {
this._ipcHandlePath = generateRandomPipeName();
+ // NOTE@coder: Write this out so we can get the most recent path.
+ fs.promises.writeFile(join(tmpdir(), "vscode-ipc"), this._ipcHandlePath).catch((error) => {
+ this.logService.error(error);
+ });
+
try {
this._server.listen(this.ipcHandlePath);
this._server.on('error', err => this.logService.error(err));
diff --git a/src/vs/workbench/api/worker/extHost.worker.services.ts b/src/vs/workbench/api/worker/extHost.worker.services.ts
index 3843fdec386edc09a1d361b63de892a04e0070ed..8aac4df527857e964798362a69f5591bef07c165 100644
--- a/src/vs/workbench/api/worker/extHost.worker.services.ts
...
...
src/node/cli.ts
浏览文件 @
fe19391c
...
...
@@ -5,7 +5,7 @@ import * as os from "os"
import
*
as
path
from
"
path
"
import
{
Args
as
VsArgs
}
from
"
../../lib/vscode/src/vs/server/ipc
"
import
{
AuthType
}
from
"
./http
"
import
{
generatePassword
,
humanPath
,
paths
}
from
"
./util
"
import
{
canConnect
,
generatePassword
,
humanPath
,
paths
}
from
"
./util
"
export
class
Optional
<
T
>
{
public
constructor
(
public
readonly
value
?:
T
)
{}
...
...
@@ -512,7 +512,35 @@ export const shouldOpenInExistingInstance = async (args: Args): Promise<string |
return
process
.
env
.
VSCODE_IPC_HOOK_CLI
}
// TODO: implement
const
readSocketPath
=
async
():
Promise
<
string
|
undefined
>
=>
{
try
{
return
await
fs
.
readFile
(
path
.
join
(
os
.
tmpdir
(),
"
vscode-ipc
"
),
"
utf8
"
)
}
catch
(
error
)
{
if
(
error
.
code
!==
"
ENOENT
"
)
{
throw
error
}
}
return
undefined
}
// If these flags are set then assume the user is trying to open in an
// existing instance since these flags have no effect otherwise.
const
openInFlagCount
=
[
"
reuse-window
"
,
"
new-window
"
].
reduce
((
prev
,
cur
)
=>
{
return
args
[
cur
as
keyof
Args
]
?
prev
+
1
:
prev
},
0
)
if
(
openInFlagCount
>
0
)
{
return
readSocketPath
()
}
// It's possible the user is trying to spawn another instance of code-server.
// Check if any unrelated flags are set (add one for `_` which always exists),
// that a file or directory was passed, and that the socket is active.
if
(
Object
.
keys
(
args
).
length
===
openInFlagCount
+
1
&&
args
.
_
.
length
>
0
)
{
const
socketPath
=
await
readSocketPath
()
if
(
socketPath
&&
(
await
canConnect
(
socketPath
)))
{
return
socketPath
}
}
return
undefined
}
src/node/socket.ts
浏览文件 @
fe19391c
...
...
@@ -4,7 +4,7 @@ import * as path from "path"
import
*
as
tls
from
"
tls
"
import
{
Emitter
}
from
"
../common/emitter
"
import
{
generateUuid
}
from
"
../common/util
"
import
{
tmpdir
}
from
"
./util
"
import
{
canConnect
,
tmpdir
}
from
"
./util
"
/**
* Provides a way to proxy a TLS socket. Can be used when you need to pass a
...
...
@@ -89,17 +89,6 @@ export class SocketProxyProvider {
}
public
async
findFreeSocketPath
(
basePath
:
string
,
maxTries
=
100
):
Promise
<
string
>
{
const
canConnect
=
(
path
:
string
):
Promise
<
boolean
>
=>
{
return
new
Promise
((
resolve
)
=>
{
const
socket
=
net
.
connect
(
path
)
socket
.
once
(
"
error
"
,
()
=>
resolve
(
false
))
socket
.
once
(
"
connect
"
,
()
=>
{
socket
.
destroy
()
resolve
(
true
)
})
})
}
let
i
=
0
let
path
=
basePath
while
((
await
canConnect
(
path
))
&&
i
<
maxTries
)
{
...
...
src/node/util.ts
浏览文件 @
fe19391c
...
...
@@ -2,6 +2,7 @@ import * as cp from "child_process"
import
*
as
crypto
from
"
crypto
"
import
envPaths
from
"
env-paths
"
import
*
as
fs
from
"
fs-extra
"
import
*
as
net
from
"
net
"
import
*
as
os
from
"
os
"
import
*
as
path
from
"
path
"
import
*
as
util
from
"
util
"
...
...
@@ -246,3 +247,17 @@ export function pathToFsPath(path: string, keepDriveLetterCasing = false): strin
}
return
value
}
/**
* Return a promise that resolves with whether the socket path is active.
*/
export
function
canConnect
(
path
:
string
):
Promise
<
boolean
>
{
return
new
Promise
((
resolve
)
=>
{
const
socket
=
net
.
connect
(
path
)
socket
.
once
(
"
error
"
,
()
=>
resolve
(
false
))
socket
.
once
(
"
connect
"
,
()
=>
{
socket
.
destroy
()
resolve
(
true
)
})
})
}
test/cli.test.ts
浏览文件 @
fe19391c
import
{
Level
,
logger
}
from
"
@coder/logger
"
import
*
as
assert
from
"
assert
"
import
*
as
fs
from
"
fs-extra
"
import
*
as
net
from
"
net
"
import
*
as
os
from
"
os
"
import
*
as
path
from
"
path
"
import
{
parse
,
setDefaults
}
from
"
../src/node/cli
"
import
{
paths
}
from
"
../src/node/util
"
import
{
Args
,
parse
,
setDefaults
,
shouldOpenInExistingInstance
}
from
"
../src/node/cli
"
import
{
paths
,
tmpdir
}
from
"
../src/node/util
"
describe
(
"
cli
"
,
()
=>
{
type
Mutable
<
T
>
=
{
-
readonly
[
P
in
keyof
T
]:
T
[
P
]
}
describe
(
"
parser
"
,
()
=>
{
beforeEach
(()
=>
{
delete
process
.
env
.
LOG_LEVEL
})
// The parser should not set any defaults so the caller can determine what
// values the user actually set. These are set after calling `setDefaults`.
// values the user actually set. These are only set after explicitly calling
// `setDefaults`.
const
defaults
=
{
"
extensions-dir
"
:
path
.
join
(
paths
.
data
,
"
extensions
"
),
"
user-data-dir
"
:
paths
.
data
,
...
...
@@ -225,3 +233,76 @@ describe("cli", () => {
})
})
})
describe
(
"
cli
"
,
()
=>
{
let
args
:
Mutable
<
Args
>
=
{
_
:
[]
}
const
testDir
=
path
.
join
(
tmpdir
,
"
tests/cli
"
)
const
vscodeIpcPath
=
path
.
join
(
os
.
tmpdir
(),
"
vscode-ipc
"
)
before
(
async
()
=>
{
await
fs
.
remove
(
testDir
)
await
fs
.
mkdirp
(
testDir
)
})
beforeEach
(
async
()
=>
{
delete
process
.
env
.
VSCODE_IPC_HOOK_CLI
args
=
{
_
:
[]
}
await
fs
.
remove
(
vscodeIpcPath
)
})
it
(
"
should use existing if inside code-server
"
,
async
()
=>
{
process
.
env
.
VSCODE_IPC_HOOK_CLI
=
"
test
"
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
"
test
"
)
args
.
port
=
8081
args
.
_
.
push
(
"
./file
"
)
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
"
test
"
)
})
it
(
"
should use existing if --reuse-window is set
"
,
async
()
=>
{
args
[
"
reuse-window
"
]
=
true
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
undefined
)
await
fs
.
writeFile
(
vscodeIpcPath
,
"
test
"
)
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
"
test
"
)
args
.
port
=
8081
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
"
test
"
)
})
it
(
"
should use existing if --new-window is set
"
,
async
()
=>
{
args
[
"
new-window
"
]
=
true
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
undefined
)
await
fs
.
writeFile
(
vscodeIpcPath
,
"
test
"
)
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
"
test
"
)
args
.
port
=
8081
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
"
test
"
)
})
it
(
"
should use existing if no unrelated flags are set, has positional, and socket is active
"
,
async
()
=>
{
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
undefined
)
args
.
_
.
push
(
"
./file
"
)
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
undefined
)
const
socketPath
=
path
.
join
(
testDir
,
"
socket
"
)
await
fs
.
writeFile
(
vscodeIpcPath
,
socketPath
)
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
undefined
)
await
new
Promise
((
resolve
)
=>
{
const
server
=
net
.
createServer
(()
=>
{
// Close after getting the first connection.
server
.
close
()
})
server
.
once
(
"
listening
"
,
()
=>
resolve
(
server
))
server
.
listen
(
socketPath
)
})
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
socketPath
)
args
.
port
=
8081
assert
.
strictEqual
(
await
shouldOpenInExistingInstance
(
args
),
undefined
)
})
})
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录