Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
一杯枸杞茶ya
csdn-workflow
提交
7282ef2b
C
csdn-workflow
项目概览
一杯枸杞茶ya
/
csdn-workflow
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
csdn-workflow
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7282ef2b
编写于
1月 26, 2021
作者:
T
Tomas Vik
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(git_service): move getInstanceUrl to separate util function
上级
ed379108
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
103 addition
and
113 deletion
+103
-113
src/__mocks__/vscode.js
src/__mocks__/vscode.js
+3
-0
src/git_service.test.ts
src/git_service.test.ts
+0
-2
src/git_service.ts
src/git_service.ts
+3
-91
src/gitlab_service.ts
src/gitlab_service.ts
+2
-6
src/search_input.js
src/search_input.js
+2
-2
src/service_factory.ts
src/service_factory.ts
+3
-8
src/services/workspace_service.ts
src/services/workspace_service.ts
+2
-2
src/utils/get_instance_url.ts
src/utils/get_instance_url.ts
+86
-0
test/integration/services/workspace_service.test.js
test/integration/services/workspace_service.test.js
+2
-2
未找到文件。
src/__mocks__/vscode.js
浏览文件 @
7282ef2b
...
...
@@ -28,6 +28,9 @@ module.exports = {
commands
:
{
executeCommand
:
jest
.
fn
(),
},
workspace
:
{
getConfiguration
:
jest
.
fn
().
mockReturnValue
({
instanceUrl
:
'
https://gitlab.com
'
}),
},
CommentMode
:
{
Preview
:
1
},
CommentThreadCollapsibleState
:
{
Expanded
:
1
},
Position
:
function
Position
(
x
,
y
)
{
...
...
src/git_service.test.ts
浏览文件 @
7282ef2b
...
...
@@ -22,10 +22,8 @@ describe('git_service', () => {
const
getDefaultOptions
=
():
GitServiceOptions
=>
({
workspaceFolder
,
instanceUrl
:
'
https://gitlab.com
'
,
remoteName
:
undefined
,
pipelineGitRemoteName
:
undefined
,
tokenService
:
{
getInstanceUrls
:
()
=>
[]
},
log
:
()
=>
{
//
},
...
...
src/git_service.ts
浏览文件 @
7282ef2b
import
*
as
execa
from
'
execa
'
;
import
*
as
url
from
'
url
'
;
import
{
GITLAB_COM_URL
}
from
'
./constants
'
;
import
{
parseGitRemote
,
GitRemote
}
from
'
./git/git_remote_parser
'
;
interface
TokenService
{
getInstanceUrls
():
string
[];
}
import
{
getInstanceUrl
}
from
'
./utils/get_instance_url
'
;
export
interface
GitServiceOptions
{
workspaceFolder
:
string
;
instanceUrl
?:
string
;
remoteName
?:
string
;
pipelineGitRemoteName
?:
string
;
tokenService
:
TokenService
;
log
:
(
line
:
string
)
=>
void
;
}
export
class
GitService
{
workspaceFolder
:
string
;
instanceUrl
?:
string
;
remoteName
?:
string
;
pipelineGitRemoteName
?:
string
;
tokenService
:
TokenService
;
log
:
(
line
:
string
)
=>
void
;
constructor
(
options
:
GitServiceOptions
)
{
this
.
instanceUrl
=
options
.
instanceUrl
;
this
.
remoteName
=
options
.
remoteName
;
this
.
pipelineGitRemoteName
=
options
.
pipelineGitRemoteName
;
this
.
workspaceFolder
=
options
.
workspaceFolder
;
this
.
tokenService
=
options
.
tokenService
;
this
.
log
=
options
.
log
;
}
private
async
fetch
(
cmd
:
string
):
Promise
<
string
|
null
>
{
const
[
git
,
...
args
]
=
cmd
.
trim
().
split
(
'
'
);
let
currentWorkspaceFolder
=
this
.
workspaceFolder
;
if
(
currentWorkspaceFolder
==
null
)
{
currentWorkspaceFolder
=
''
;
}
try
{
const
{
stdout
}
=
await
execa
(
git
,
args
,
{
cwd
:
currentW
orkspaceFolder
,
cwd
:
this
.
w
orkspaceFolder
,
preferLocal
:
false
,
});
return
stdout
;
...
...
@@ -74,7 +56,7 @@ export class GitService {
}
if
(
remoteUrl
)
{
return
parseGitRemote
(
await
this
.
fetchCurrentInstanceUrl
(
),
remoteUrl
);
return
parseGitRemote
(
await
getInstanceUrl
(
this
.
workspaceFolder
),
remoteUrl
);
}
return
null
;
...
...
@@ -121,74 +103,4 @@ export class GitService {
return
branchName
;
}
private
async
fetchGitRemoteUrls
():
Promise
<
string
[]
>
{
const
fetchGitRemotesVerbose
=
async
():
Promise
<
string
[]
>
=>
{
const
output
=
await
this
.
fetch
(
'
git remote -v
'
);
return
(
output
||
''
).
split
(
'
\n
'
);
};
const
parseRemoteFromVerboseLine
=
(
line
:
string
)
=>
{
// git remote -v output looks like
// origin[TAB]git@gitlab.com:gitlab-org/gitlab-vscode-extension.git[WHITESPACE](fetch)
// the interesting part is surrounded by a tab symbol and a whitespace
return
line
.
split
(
/
\t
| /
)[
1
];
};
const
remotes
=
await
fetchGitRemotesVerbose
();
const
remoteUrls
=
remotes
.
map
(
remote
=>
parseRemoteFromVerboseLine
(
remote
)).
filter
(
Boolean
);
// git remote -v returns a (fetch) and a (push) line for each remote,
// so we need to remove duplicates
return
[...
new
Set
(
remoteUrls
)];
}
private
async
intersectionOfInstanceAndTokenUrls
()
{
const
uriHostname
=
(
uri
:
string
)
=>
url
.
parse
(
uri
).
host
;
const
instanceUrls
=
this
.
tokenService
.
getInstanceUrls
();
const
gitRemotes
=
await
this
.
fetchGitRemoteUrls
();
const
gitRemoteHosts
=
gitRemotes
.
map
(
uriHostname
);
return
instanceUrls
.
filter
(
host
=>
gitRemoteHosts
.
includes
(
uriHostname
(
host
)));
}
private
async
heuristicInstanceUrl
()
{
// if the intersection of git remotes and configured PATs exists and is exactly
// one hostname, use it
const
intersection
=
await
this
.
intersectionOfInstanceAndTokenUrls
();
if
(
intersection
.
length
===
1
)
{
const
heuristicUrl
=
intersection
[
0
];
this
.
log
(
`Found
${
heuristicUrl
}
in the PAT list and git remotes, using it as the instanceUrl`
,
);
return
heuristicUrl
;
}
if
(
intersection
.
length
>
1
)
{
this
.
log
(
`Found more than one intersection of git remotes and configured PATs,
${
intersection
}
`
,
);
}
return
null
;
}
async
fetchCurrentInstanceUrl
():
Promise
<
string
>
{
// if the workspace setting exists, use it
if
(
this
.
instanceUrl
)
{
return
this
.
instanceUrl
;
}
// try to determine the instance URL heuristically
const
heuristicUrl
=
await
this
.
heuristicInstanceUrl
();
if
(
heuristicUrl
)
{
return
heuristicUrl
;
}
// default to Gitlab cloud
return
GITLAB_COM_URL
;
}
}
src/gitlab_service.ts
浏览文件 @
7282ef2b
...
...
@@ -13,6 +13,7 @@ import { CustomQueryType } from './gitlab/custom_query_type';
import
{
CustomQuery
}
from
'
./gitlab/custom_query
'
;
import
{
getAvatarUrl
}
from
'
./utils/get_avatar_url
'
;
import
{
getHttpAgentOptions
}
from
'
./utils/get_http_agent_options
'
;
import
{
getInstanceUrl
as
getInstanceUrlUtil
}
from
'
./utils/get_instance_url
'
;
interface
GitLabProject
{
id
:
number
;
...
...
@@ -46,12 +47,7 @@ const normalizeAvatarUrl = (instanceUrl: string) => (issuable: RestIssuable): Re
const
projectCache
:
Record
<
string
,
GitLabProject
>
=
{};
let
versionCache
:
string
|
null
=
null
;
const
getInstanceUrl
=
async
()
=>
await
createGitService
(
// fetching of instanceUrl is the only GitService method that doesn't need workspaceFolder
// TODO: remove this default value once we implement https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/260
(
await
getCurrentWorkspaceFolder
())
||
''
,
).
fetchCurrentInstanceUrl
();
const
getInstanceUrl
=
async
()
=>
await
getInstanceUrlUtil
(
await
getCurrentWorkspaceFolder
());
async
function
fetch
(
path
:
string
,
method
=
'
GET
'
,
data
?:
Record
<
string
,
unknown
>
)
{
const
instanceUrl
=
await
getInstanceUrl
();
...
...
src/search_input.js
浏览文件 @
7282ef2b
...
...
@@ -2,7 +2,7 @@ const vscode = require('vscode');
const
gitLabService
=
require
(
'
./gitlab_service
'
);
const
openers
=
require
(
'
./openers
'
);
const
{
getCurrentWorkspaceFolderOrSelectOne
}
=
require
(
'
./services/workspace_service
'
);
const
{
createGitService
}
=
require
(
'
./service_factory
'
);
const
{
getInstanceUrl
}
=
require
(
'
./utils/get_instance_url
'
);
const
parseQuery
=
(
query
,
noteableType
)
=>
{
const
params
=
{};
...
...
@@ -121,7 +121,7 @@ async function showProjectAdvancedSearchInput() {
'
Project Advanced Search. (Check extension page for Advanced Search)
'
,
);
const
queryString
=
await
encodeURIComponent
(
query
);
const
instanceUrl
=
await
createGitService
(
workspaceFolder
).
fetchCurrentInstanceUrl
(
);
const
instanceUrl
=
await
getInstanceUrl
(
workspaceFolder
);
// Select issues tab by default for Advanced Search
await
openers
.
openUrl
(
...
...
src/service_factory.ts
浏览文件 @
7282ef2b
import
*
as
vscode
from
'
vscode
'
;
import
{
GitService
}
from
'
./git_service
'
;
import
{
tokenService
}
from
'
./services/token_service
'
;
import
{
log
}
from
'
./log
'
;
import
{
GitLabNewService
}
from
'
./gitlab/gitlab_new_service
'
;
import
{
getInstanceUrl
}
from
'
./utils/get_instance_url
'
;
export
function
createGitService
(
workspaceFolder
:
string
):
GitService
{
const
{
instanceUrl
,
remoteName
,
pipelineGitRemoteName
}
=
vscode
.
workspace
.
getConfiguration
(
'
gitlab
'
,
);
const
{
remoteName
,
pipelineGitRemoteName
}
=
vscode
.
workspace
.
getConfiguration
(
'
gitlab
'
);
// the getConfiguration() returns null for missing attributes, we need to convert them to
// undefined so that we can use optional properties and default function parameters
return
new
GitService
({
workspaceFolder
,
instanceUrl
:
instanceUrl
||
undefined
,
remoteName
:
remoteName
||
undefined
,
pipelineGitRemoteName
:
pipelineGitRemoteName
||
undefined
,
tokenService
,
log
,
});
}
export
async
function
createGitLabNewService
(
workspaceFolder
:
string
):
Promise
<
GitLabNewService
>
{
const
gitService
=
createGitService
(
workspaceFolder
);
return
new
GitLabNewService
(
await
gitService
.
fetchCurrentInstanceUrl
());
return
new
GitLabNewService
(
await
getInstanceUrl
(
workspaceFolder
));
}
src/services/workspace_service.ts
浏览文件 @
7282ef2b
...
...
@@ -9,7 +9,7 @@ async function getWorkspaceFolderForOpenEditor(): Promise<string | undefined> {
return
workspaceFolder
?.
uri
.
fsPath
;
}
export
async
function
getCurrentWorkspaceFolder
():
Promise
<
string
|
null
>
{
export
async
function
getCurrentWorkspaceFolder
():
Promise
<
string
|
undefined
>
{
const
editorFolder
=
await
getWorkspaceFolderForOpenEditor
();
if
(
editorFolder
)
{
...
...
@@ -21,7 +21,7 @@ export async function getCurrentWorkspaceFolder(): Promise<string | null> {
return
workspaceFolders
[
0
].
uri
.
fsPath
;
}
return
null
;
return
undefined
;
}
export
async
function
getCurrentWorkspaceFolderOrSelectOne
():
Promise
<
string
|
null
>
{
...
...
src/utils/get_instance_url.ts
0 → 100644
浏览文件 @
7282ef2b
import
*
as
vscode
from
'
vscode
'
;
import
*
as
execa
from
'
execa
'
;
import
*
as
url
from
'
url
'
;
import
{
GITLAB_COM_URL
}
from
'
../constants
'
;
import
{
tokenService
}
from
'
../services/token_service
'
;
import
{
log
}
from
'
../log
'
;
async
function
fetch
(
cmd
:
string
,
workspaceFolder
:
string
):
Promise
<
string
|
null
>
{
const
[
git
,
...
args
]
=
cmd
.
trim
().
split
(
'
'
);
const
{
stdout
}
=
await
execa
(
git
,
args
,
{
cwd
:
workspaceFolder
,
preferLocal
:
false
,
});
return
stdout
;
}
async
function
fetchGitRemoteUrls
(
workspaceFolder
:
string
):
Promise
<
string
[]
>
{
const
fetchGitRemotesVerbose
=
async
():
Promise
<
string
[]
>
=>
{
const
output
=
await
fetch
(
'
git remote -v
'
,
workspaceFolder
);
return
(
output
||
''
).
split
(
'
\n
'
);
};
const
parseRemoteFromVerboseLine
=
(
line
:
string
)
=>
{
// git remote -v output looks like
// origin[TAB]git@gitlab.com:gitlab-org/gitlab-vscode-extension.git[WHITESPACE](fetch)
// the interesting part is surrounded by a tab symbol and a whitespace
return
line
.
split
(
/
\t
| /
)[
1
];
};
const
remotes
=
await
fetchGitRemotesVerbose
();
const
remoteUrls
=
remotes
.
map
(
remote
=>
parseRemoteFromVerboseLine
(
remote
)).
filter
(
Boolean
);
// git remote -v returns a (fetch) and a (push) line for each remote,
// so we need to remove duplicates
return
[...
new
Set
(
remoteUrls
)];
}
async
function
intersectionOfInstanceAndTokenUrls
(
workspaceFolder
:
string
)
{
const
uriHostname
=
(
uri
:
string
)
=>
url
.
parse
(
uri
).
host
;
const
instanceUrls
=
tokenService
.
getInstanceUrls
();
const
gitRemotes
=
await
fetchGitRemoteUrls
(
workspaceFolder
);
const
gitRemoteHosts
=
gitRemotes
.
map
(
uriHostname
);
return
instanceUrls
.
filter
(
host
=>
gitRemoteHosts
.
includes
(
uriHostname
(
host
)));
}
async
function
heuristicInstanceUrl
(
workspaceFolder
:
string
)
{
// if the intersection of git remotes and configured PATs exists and is exactly
// one hostname, use it
const
intersection
=
await
intersectionOfInstanceAndTokenUrls
(
workspaceFolder
);
if
(
intersection
.
length
===
1
)
{
const
heuristicUrl
=
intersection
[
0
];
log
(
`Found
${
heuristicUrl
}
in the PAT list and git remotes, using it as the instanceUrl`
);
return
heuristicUrl
;
}
if
(
intersection
.
length
>
1
)
{
log
(
`Found more than one intersection of git remotes and configured PATs,
${
intersection
}
`
);
}
return
null
;
}
export
async
function
getInstanceUrl
(
workspaceFolder
?:
string
):
Promise
<
string
>
{
const
{
instanceUrl
}
=
vscode
.
workspace
.
getConfiguration
(
'
gitlab
'
);
// if the workspace setting exists, use it
if
(
instanceUrl
)
{
return
instanceUrl
;
}
// legacy logic in GitLabService might not have the workspace folder available
// in that case we just skip the heuristic
if
(
workspaceFolder
)
{
// try to determine the instance URL heuristically
const
heuristicUrl
=
await
heuristicInstanceUrl
(
workspaceFolder
);
if
(
heuristicUrl
)
{
return
heuristicUrl
;
}
}
// default to Gitlab cloud
return
GITLAB_COM_URL
;
}
test/integration/services/workspace_service.test.js
浏览文件 @
7282ef2b
...
...
@@ -46,9 +46,9 @@ describe('workspace_service', () => {
sandbox
.
restore
();
});
it
(
'
getCurrentWorkspaceFolder returns
null
'
,
async
()
=>
{
it
(
'
getCurrentWorkspaceFolder returns
undefined
'
,
async
()
=>
{
const
result
=
await
workspaceService
.
getCurrentWorkspaceFolder
();
assert
.
strictEqual
(
result
,
null
);
assert
.
strictEqual
(
result
,
undefined
);
});
it
(
'
getCurrentWorkspaceFolderOrSelectOne lets user select a workspace
'
,
async
()
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录