Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
1ab3fd8f
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1ab3fd8f
编写于
12月 14, 2017
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'submodules'
上级
35369b7e
cbb59c68
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
664 addition
and
71 deletion
+664
-71
extensions/git/package.json
extensions/git/package.json
+9
-0
extensions/git/package.nls.json
extensions/git/package.nls.json
+2
-1
extensions/git/src/commands.ts
extensions/git/src/commands.ts
+30
-4
extensions/git/src/contentProvider.ts
extensions/git/src/contentProvider.ts
+13
-3
extensions/git/src/decorationProvider.ts
extensions/git/src/decorationProvider.ts
+16
-0
extensions/git/src/git.ts
extensions/git/src/git.ts
+100
-1
extensions/git/src/model.ts
extensions/git/src/model.ts
+41
-6
extensions/git/src/repository.ts
extensions/git/src/repository.ts
+32
-16
extensions/git/src/test/git.test.ts
extensions/git/src/test/git.test.ts
+41
-1
extensions/git/src/uri.ts
extensions/git/src/uri.ts
+32
-7
extensions/git/src/util.ts
extensions/git/src/util.ts
+4
-0
extensions/gitsyntax/OSSREADME.json
extensions/gitsyntax/OSSREADME.json
+41
-28
extensions/gitsyntax/diff.language-configuration.json
extensions/gitsyntax/diff.language-configuration.json
+11
-0
extensions/gitsyntax/package.json
extensions/gitsyntax/package.json
+24
-4
extensions/gitsyntax/syntaxes/diff.tmLanguage
extensions/gitsyntax/syntaxes/diff.tmLanguage
+268
-0
未找到文件。
extensions/git/package.json
浏览文件 @
1ab3fd8f
...
...
@@ -951,6 +951,15 @@
"dark"
:
"#6c6cc4"
,
"highContrast"
:
"#6c6cc4"
}
},
{
"id"
:
"gitDecoration.submoduleResourceForeground"
,
"description"
:
"%colors.submodule%"
,
"defaults"
:
{
"light"
:
"#1258a7"
,
"dark"
:
"#8db9e2"
,
"highContrast"
:
"#8db9e2"
}
}
]
},
...
...
extensions/git/package.nls.json
浏览文件 @
1ab3fd8f
...
...
@@ -68,5 +68,6 @@
"colors.deleted"
:
"Color for deleted resources."
,
"colors.untracked"
:
"Color for untracked resources."
,
"colors.ignored"
:
"Color for ignored resources."
,
"colors.conflict"
:
"Color for resources with conflicts."
"colors.conflict"
:
"Color for resources with conflicts."
,
"colors.submodule"
:
"Color for submodule resources."
}
\ No newline at end of file
extensions/git/src/commands.ts
浏览文件 @
1ab3fd8f
...
...
@@ -7,12 +7,13 @@
import
{
Uri
,
commands
,
Disposable
,
window
,
workspace
,
QuickPickItem
,
OutputChannel
,
Range
,
WorkspaceEdit
,
Position
,
LineChange
,
SourceControlResourceState
,
TextDocumentShowOptions
,
ViewColumn
,
ProgressLocation
,
TextEditor
,
CancellationTokenSource
,
StatusBarAlignment
}
from
'
vscode
'
;
import
{
Ref
,
RefType
,
Git
,
GitErrorCodes
,
Branch
}
from
'
./git
'
;
import
{
Repository
,
Resource
,
Status
,
CommitOptions
,
ResourceGroupType
}
from
'
./repository
'
;
import
{
Repository
,
Resource
,
Status
,
CommitOptions
,
ResourceGroupType
,
RepositoryState
}
from
'
./repository
'
;
import
{
Model
}
from
'
./model
'
;
import
{
toGitUri
,
fromGitUri
}
from
'
./uri
'
;
import
{
grep
,
eventToPromise
,
isDescendant
}
from
'
./util
'
;
import
{
applyLineChanges
,
intersectDiffWithRange
,
toLineRanges
,
invertLineChange
}
from
'
./staging
'
;
import
*
as
path
from
'
path
'
;
import
{
lstat
,
Stats
}
from
'
fs
'
;
import
*
as
os
from
'
os
'
;
import
TelemetryReporter
from
'
vscode-extension-telemetry
'
;
import
*
as
nls
from
'
vscode-nls
'
;
...
...
@@ -168,8 +169,28 @@ export class CommandCenter {
}
private
async
_openResource
(
resource
:
Resource
,
preview
?:
boolean
,
preserveFocus
?:
boolean
,
preserveSelection
?:
boolean
):
Promise
<
void
>
{
const
left
=
await
this
.
getLeftResource
(
resource
);
const
right
=
await
this
.
getRightResource
(
resource
);
let
stat
:
Stats
|
undefined
;
try
{
stat
=
await
new
Promise
<
Stats
>
((
c
,
e
)
=>
lstat
(
resource
.
resourceUri
.
fsPath
,
(
err
,
stat
)
=>
err
?
e
(
err
)
:
c
(
stat
)));
}
catch
(
err
)
{
// noop
}
let
left
:
Uri
|
undefined
;
let
right
:
Uri
|
undefined
;
if
(
stat
&&
stat
.
isDirectory
())
{
const
repository
=
this
.
model
.
getRepositoryForSubmodule
(
resource
.
resourceUri
);
if
(
repository
)
{
right
=
toGitUri
(
resource
.
resourceUri
,
resource
.
resourceGroupType
===
ResourceGroupType
.
Index
?
'
index
'
:
'
wt
'
,
{
submoduleOf
:
repository
.
root
});
}
}
else
{
left
=
await
this
.
getLeftResource
(
resource
);
right
=
await
this
.
getRightResource
(
resource
);
}
const
title
=
this
.
getTitle
(
resource
);
if
(
!
right
)
{
...
...
@@ -1689,13 +1710,18 @@ export class CommandCenter {
const
isSingleResource
=
arg
instanceof
Uri
;
const
groups
=
resources
.
reduce
((
result
,
resource
)
=>
{
cons
t
repository
=
this
.
model
.
getRepository
(
resource
);
le
t
repository
=
this
.
model
.
getRepository
(
resource
);
if
(
!
repository
)
{
console
.
warn
(
'
Could not find git repository for
'
,
resource
);
return
result
;
}
// Could it be a submodule?
if
(
resource
.
fsPath
===
repository
.
root
)
{
repository
=
this
.
model
.
getRepositoryForSubmodule
(
resource
)
||
repository
;
}
const
tuple
=
result
.
filter
(
p
=>
p
.
repository
===
repository
)[
0
];
if
(
tuple
)
{
...
...
extensions/git/src/contentProvider.ts
浏览文件 @
1ab3fd8f
...
...
@@ -52,7 +52,7 @@ export class GitContentProvider {
return
;
}
this
.
_onDidChange
.
fire
(
toGitUri
(
uri
,
''
,
true
));
this
.
_onDidChange
.
fire
(
toGitUri
(
uri
,
''
,
{
replaceFileExtension
:
true
}
));
}
@
debounce
(
1100
)
...
...
@@ -83,6 +83,18 @@ export class GitContentProvider {
}
async
provideTextDocumentContent
(
uri
:
Uri
):
Promise
<
string
>
{
let
{
path
,
ref
,
submoduleOf
}
=
fromGitUri
(
uri
);
if
(
submoduleOf
)
{
const
repository
=
this
.
model
.
getRepository
(
submoduleOf
);
if
(
!
repository
)
{
return
''
;
}
return
await
repository
.
diff
(
path
,
{
cached
:
ref
===
'
index
'
});
}
const
repository
=
this
.
model
.
getRepository
(
uri
);
if
(
!
repository
)
{
...
...
@@ -95,8 +107,6 @@ export class GitContentProvider {
this
.
cache
[
cacheKey
]
=
cacheValue
;
let
{
path
,
ref
}
=
fromGitUri
(
uri
);
if
(
ref
===
'
~
'
)
{
const
fileUri
=
Uri
.
file
(
path
);
const
uriString
=
fileUri
.
toString
();
...
...
extensions/git/src/decorationProvider.ts
浏览文件 @
1ab3fd8f
...
...
@@ -6,10 +6,12 @@
'
use strict
'
;
import
{
window
,
workspace
,
Uri
,
Disposable
,
Event
,
EventEmitter
,
DecorationData
,
DecorationProvider
,
ThemeColor
}
from
'
vscode
'
;
import
*
as
path
from
'
path
'
;
import
{
Repository
,
GitResourceGroup
,
Status
}
from
'
./repository
'
;
import
{
Model
}
from
'
./model
'
;
import
{
debounce
}
from
'
./decorators
'
;
import
{
filterEvent
}
from
'
./util
'
;
import
{
Submodule
}
from
'
./git
'
;
class
GitIgnoreDecorationProvider
implements
DecorationProvider
{
...
...
@@ -65,6 +67,12 @@ class GitIgnoreDecorationProvider implements DecorationProvider {
class
GitDecorationProvider
implements
DecorationProvider
{
private
static
SubmoduleDecorationData
:
DecorationData
=
{
title
:
'
Submodule
'
,
abbreviation
:
'
S
'
,
color
:
new
ThemeColor
(
'
gitDecoration.submoduleResourceForeground
'
)
};
private
readonly
_onDidChangeDecorations
=
new
EventEmitter
<
Uri
[]
>
();
readonly
onDidChangeDecorations
:
Event
<
Uri
[]
>
=
this
.
_onDidChangeDecorations
.
event
;
...
...
@@ -80,6 +88,8 @@ class GitDecorationProvider implements DecorationProvider {
private
onDidRunGitStatus
():
void
{
let
newDecorations
=
new
Map
<
string
,
DecorationData
>
();
this
.
collectSubmoduleDecorationData
(
newDecorations
);
this
.
collectDecorationData
(
this
.
repository
.
indexGroup
,
newDecorations
);
this
.
collectDecorationData
(
this
.
repository
.
workingTreeGroup
,
newDecorations
);
this
.
collectDecorationData
(
this
.
repository
.
mergeGroup
,
newDecorations
);
...
...
@@ -101,6 +111,12 @@ class GitDecorationProvider implements DecorationProvider {
});
}
private
collectSubmoduleDecorationData
(
bucket
:
Map
<
string
,
DecorationData
>
):
void
{
for
(
const
submodule
of
this
.
repository
.
submodules
)
{
bucket
.
set
(
Uri
.
file
(
path
.
join
(
this
.
repository
.
root
,
submodule
.
path
)).
toString
(),
GitDecorationProvider
.
SubmoduleDecorationData
);
}
}
provideDecoration
(
uri
:
Uri
):
DecorationData
|
undefined
{
return
this
.
decorations
.
get
(
uri
.
toString
());
}
...
...
extensions/git/src/git.ts
浏览文件 @
1ab3fd8f
...
...
@@ -15,7 +15,7 @@ import * as filetype from 'file-type';
import
{
assign
,
uniqBy
,
groupBy
,
denodeify
,
IDisposable
,
toDisposable
,
dispose
,
mkdirp
,
readBytes
,
detectUnicodeEncoding
,
Encoding
,
onceEvent
}
from
'
./util
'
;
import
{
CancellationToken
}
from
'
vscode
'
;
const
readfile
=
denodeify
<
string
>
(
fs
.
readFile
);
const
readfile
=
denodeify
<
string
,
string
|
null
,
string
>
(
fs
.
readFile
);
export
interface
IGit
{
path
:
string
;
...
...
@@ -535,6 +535,72 @@ export class GitStatusParser {
}
}
export
interface
Submodule
{
name
:
string
;
path
:
string
;
url
:
string
;
}
export
function
parseGitmodules
(
raw
:
string
):
Submodule
[]
{
const
regex
=
/
\r?\n
/g
;
let
position
=
0
;
let
match
:
RegExpExecArray
|
null
=
null
;
const
result
:
Submodule
[]
=
[];
let
submodule
:
Partial
<
Submodule
>
=
{};
function
parseLine
(
line
:
string
):
void
{
const
sectionMatch
=
/^
\s
*
\[
submodule "
([^
"
]
+
)
"
\]\s
*$/
.
exec
(
line
);
if
(
sectionMatch
)
{
if
(
submodule
.
name
&&
submodule
.
path
&&
submodule
.
url
)
{
result
.
push
(
submodule
as
Submodule
);
}
const
name
=
sectionMatch
[
1
];
if
(
name
)
{
submodule
=
{
name
};
return
;
}
}
if
(
!
submodule
)
{
return
;
}
const
propertyMatch
=
/^
\s
*
(\w
+
)
=
(
.*
)
$/
.
exec
(
line
);
if
(
!
propertyMatch
)
{
return
;
}
const
[,
key
,
value
]
=
propertyMatch
;
switch
(
key
)
{
case
'
path
'
:
submodule
.
path
=
value
;
break
;
case
'
url
'
:
submodule
.
url
=
value
;
break
;
}
}
while
(
match
=
regex
.
exec
(
raw
))
{
parseLine
(
raw
.
substring
(
position
,
match
.
index
));
position
=
match
.
index
+
match
[
0
].
length
;
}
parseLine
(
raw
.
substring
(
position
));
if
(
submodule
.
name
&&
submodule
.
path
&&
submodule
.
url
)
{
result
.
push
(
submodule
as
Submodule
);
}
return
result
;
}
export
interface
DiffOptions
{
cached
?:
boolean
;
}
export
class
Repository
{
constructor
(
...
...
@@ -673,6 +739,19 @@ export class Repository {
}
}
async
diff
(
path
:
string
,
options
:
DiffOptions
=
{}):
Promise
<
string
>
{
const
args
=
[
'
diff
'
];
if
(
options
.
cached
)
{
args
.
push
(
'
--cached
'
);
}
args
.
push
(
'
--
'
,
path
);
const
result
=
await
this
.
run
(
args
);
return
result
.
stdout
;
}
async
add
(
paths
:
string
[]):
Promise
<
void
>
{
const
args
=
[
'
add
'
,
'
-A
'
,
'
--
'
];
...
...
@@ -1181,4 +1260,24 @@ export class Repository {
return
{
hash
:
match
[
1
],
message
:
match
[
2
]
};
}
async
updateSubmodules
(
paths
:
string
[]):
Promise
<
void
>
{
const
args
=
[
'
submodule
'
,
'
update
'
,
'
--
'
,
...
paths
];
await
this
.
run
(
args
);
}
async
getSubmodules
():
Promise
<
Submodule
[]
>
{
const
gitmodulesPath
=
path
.
join
(
this
.
root
,
'
.gitmodules
'
);
try
{
const
gitmodulesRaw
=
await
readfile
(
gitmodulesPath
,
'
utf8
'
);
return
parseGitmodules
(
gitmodulesRaw
);
}
catch
(
err
)
{
if
(
/ENOENT/
.
test
(
err
.
message
))
{
return
[];
}
throw
err
;
}
}
}
extensions/git/src/model.ts
浏览文件 @
1ab3fd8f
...
...
@@ -101,8 +101,11 @@ export class Model {
}
private
onPossibleGitRepositoryChange
(
uri
:
Uri
):
void
{
const
possibleGitRepositoryPath
=
uri
.
fsPath
.
replace
(
/
\.
git.*$/
,
''
);
this
.
possibleGitRepositoryPaths
.
add
(
possibleGitRepositoryPath
);
this
.
eventuallyScanPossibleGitRepository
(
uri
.
fsPath
.
replace
(
/
\.
git.*$/
,
''
));
}
private
eventuallyScanPossibleGitRepository
(
path
:
string
)
{
this
.
possibleGitRepositoryPaths
.
add
(
path
);
this
.
eventuallyScanPossibleGitRepositories
();
}
...
...
@@ -213,11 +216,20 @@ export class Model {
const
disappearListener
=
onDidDisappearRepository
(()
=>
dispose
());
const
changeListener
=
repository
.
onDidChangeRepository
(
uri
=>
this
.
_onDidChangeRepository
.
fire
({
repository
,
uri
}));
const
originalResourceChangeListener
=
repository
.
onDidChangeOriginalResource
(
uri
=>
this
.
_onDidChangeOriginalResource
.
fire
({
repository
,
uri
}));
const
scanSubmodules
=
()
=>
{
repository
.
submodules
.
map
(
r
=>
path
.
join
(
repository
.
root
,
r
.
path
))
.
forEach
(
p
=>
this
.
eventuallyScanPossibleGitRepository
(
p
));
};
const
statusListener
=
repository
.
onDidRunGitStatus
(
scanSubmodules
);
scanSubmodules
();
const
dispose
=
()
=>
{
disappearListener
.
dispose
();
changeListener
.
dispose
();
originalResourceChangeListener
.
dispose
();
statusListener
.
dispose
();
repository
.
dispose
();
this
.
openRepositories
=
this
.
openRepositories
.
filter
(
e
=>
e
!==
openRepository
);
...
...
@@ -281,12 +293,21 @@ export class Model {
if
(
hint
instanceof
Uri
)
{
const
resourcePath
=
hint
.
fsPath
;
for
(
const
liveRepository
of
this
.
openRepositories
)
{
const
relativePath
=
path
.
relative
(
liveRepository
.
repository
.
root
,
resourcePath
);
outer
:
for
(
const
liveRepository
of
this
.
openRepositories
.
sort
((
a
,
b
)
=>
b
.
repository
.
root
.
length
-
a
.
repository
.
root
.
length
))
{
if
(
!
isDescendant
(
liveRepository
.
repository
.
root
,
resourcePath
))
{
continue
;
}
for
(
const
submodule
of
liveRepository
.
repository
.
submodules
)
{
const
submoduleRoot
=
path
.
join
(
liveRepository
.
repository
.
root
,
submodule
.
path
);
if
(
isDescendant
(
liveRepository
.
repository
.
root
,
resourcePath
))
{
return
liveRepository
;
if
(
isDescendant
(
submoduleRoot
,
resourcePath
))
{
continue
outer
;
}
}
return
liveRepository
;
}
return
undefined
;
...
...
@@ -307,6 +328,20 @@ export class Model {
return
undefined
;
}
getRepositoryForSubmodule
(
submoduleUri
:
Uri
):
Repository
|
undefined
{
for
(
const
repository
of
this
.
repositories
)
{
for
(
const
submodule
of
repository
.
submodules
)
{
const
submodulePath
=
path
.
join
(
repository
.
root
,
submodule
.
path
);
if
(
submodulePath
===
submoduleUri
.
fsPath
)
{
return
repository
;
}
}
}
return
undefined
;
}
dispose
():
void
{
const
openRepositories
=
[...
this
.
openRepositories
];
openRepositories
.
forEach
(
r
=>
r
.
dispose
());
...
...
extensions/git/src/repository.ts
浏览文件 @
1ab3fd8f
...
...
@@ -6,7 +6,7 @@
'
use strict
'
;
import
{
Uri
,
Command
,
EventEmitter
,
Event
,
scm
,
SourceControl
,
SourceControlInputBox
,
SourceControlResourceGroup
,
SourceControlResourceState
,
SourceControlResourceDecorations
,
Disposable
,
ProgressLocation
,
window
,
workspace
,
WorkspaceEdit
,
ThemeColor
,
DecorationData
,
Memento
}
from
'
vscode
'
;
import
{
Repository
as
BaseRepository
,
Ref
,
Branch
,
Remote
,
Commit
,
GitErrorCodes
,
Stash
,
RefType
,
GitError
}
from
'
./git
'
;
import
{
Repository
as
BaseRepository
,
Ref
,
Branch
,
Remote
,
Commit
,
GitErrorCodes
,
Stash
,
RefType
,
GitError
,
Submodule
,
DiffOptions
}
from
'
./git
'
;
import
{
anyEvent
,
filterEvent
,
eventToPromise
,
dispose
,
find
,
isDescendant
,
IDisposable
,
onceEvent
,
EmptyDisposable
,
debounceEvent
}
from
'
./util
'
;
import
{
memoize
,
throttle
,
debounce
}
from
'
./decorators
'
;
import
{
toGitUri
}
from
'
./uri
'
;
...
...
@@ -280,6 +280,7 @@ export class Resource implements SourceControlResourceState {
export
enum
Operation
{
Status
=
'
Status
'
,
Diff
=
'
Diff
'
,
Add
=
'
Add
'
,
RevertFiles
=
'
RevertFiles
'
,
Commit
=
'
Commit
'
,
...
...
@@ -301,7 +302,8 @@ export enum Operation {
Tag
=
'
Tag
'
,
Stash
=
'
Stash
'
,
CheckIgnore
=
'
CheckIgnore
'
,
LSTree
=
'
LSTree
'
LSTree
=
'
LSTree
'
,
SubmoduleUpdate
=
'
SubmoduleUpdate
'
}
function
isReadOnly
(
operation
:
Operation
):
boolean
{
...
...
@@ -474,6 +476,11 @@ export class Repository implements Disposable {
return
this
.
_remotes
;
}
private
_submodules
:
Submodule
[]
=
[];
get
submodules
():
Submodule
[]
{
return
this
.
_submodules
;
}
private
_operations
=
new
OperationsImpl
();
get
operations
():
Operations
{
return
this
.
_operations
;
}
...
...
@@ -552,7 +559,7 @@ export class Repository implements Disposable {
return
;
}
return
toGitUri
(
uri
,
''
,
true
);
return
toGitUri
(
uri
,
''
,
{
replaceFileExtension
:
true
}
);
}
private
async
updateCommitTemplate
():
Promise
<
void
>
{
...
...
@@ -563,21 +570,15 @@ export class Repository implements Disposable {
}
}
// @throttle
// async init(): Promise<void> {
// if (this.state !== State.NotAGitRepository) {
// return;
// }
// await this.git.init(this.workspaceRoot.fsPath);
// await this.status();
// }
@
throttle
async
status
():
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Status
);
}
diff
(
path
:
string
,
options
:
DiffOptions
=
{}):
Promise
<
string
>
{
return
this
.
run
(
Operation
.
Diff
,
()
=>
this
.
repository
.
diff
(
path
,
options
));
}
async
add
(
resources
:
Uri
[]):
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Add
,
()
=>
this
.
repository
.
add
(
resources
.
map
(
r
=>
r
.
fsPath
)));
}
...
...
@@ -606,8 +607,18 @@ export class Repository implements Disposable {
await
this
.
run
(
Operation
.
Clean
,
async
()
=>
{
const
toClean
:
string
[]
=
[];
const
toCheckout
:
string
[]
=
[];
const
submodulesToUpdate
:
string
[]
=
[];
resources
.
forEach
(
r
=>
{
const
fsPath
=
r
.
fsPath
;
for
(
const
submodule
of
this
.
submodules
)
{
if
(
path
.
join
(
this
.
root
,
submodule
.
path
)
===
fsPath
)
{
submodulesToUpdate
.
push
(
fsPath
);
return
;
}
}
const
raw
=
r
.
toString
();
const
scmResource
=
find
(
this
.
workingTreeGroup
.
resourceStates
,
sr
=>
sr
.
resourceUri
.
toString
()
===
raw
);
...
...
@@ -618,11 +629,11 @@ export class Repository implements Disposable {
switch
(
scmResource
.
type
)
{
case
Status
.
UNTRACKED
:
case
Status
.
IGNORED
:
toClean
.
push
(
r
.
fsPath
);
toClean
.
push
(
fsPath
);
break
;
default
:
toCheckout
.
push
(
r
.
fsPath
);
toCheckout
.
push
(
fsPath
);
break
;
}
});
...
...
@@ -637,6 +648,10 @@ export class Repository implements Disposable {
promises
.
push
(
this
.
repository
.
checkout
(
''
,
toCheckout
));
}
if
(
submodulesToUpdate
.
length
>
0
)
{
promises
.
push
(
this
.
repository
.
updateSubmodules
(
submodulesToUpdate
));
}
await
Promise
.
all
(
promises
);
});
}
...
...
@@ -929,11 +944,12 @@ export class Repository implements Disposable {
// noop
}
const
[
refs
,
remotes
]
=
await
Promise
.
all
([
this
.
repository
.
getRefs
(),
this
.
repository
.
getRemot
es
()]);
const
[
refs
,
remotes
,
submodules
]
=
await
Promise
.
all
([
this
.
repository
.
getRefs
(),
this
.
repository
.
getRemotes
(),
this
.
repository
.
getSubmodul
es
()]);
this
.
_HEAD
=
HEAD
;
this
.
_refs
=
refs
;
this
.
_remotes
=
remotes
;
this
.
_submodules
=
submodules
;
const
index
:
Resource
[]
=
[];
const
workingTree
:
Resource
[]
=
[];
...
...
extensions/git/src/test/git.test.ts
浏览文件 @
1ab3fd8f
...
...
@@ -6,7 +6,7 @@
'
use strict
'
;
import
'
mocha
'
;
import
{
GitStatusParser
}
from
'
../git
'
;
import
{
GitStatusParser
,
parseGitmodules
}
from
'
../git
'
;
import
*
as
assert
from
'
assert
'
;
suite
(
'
git
'
,
()
=>
{
...
...
@@ -135,4 +135,44 @@ suite('git', () => {
]);
});
});
suite
(
'
parseGitmodules
'
,
()
=>
{
test
(
'
empty
'
,
()
=>
{
assert
.
deepEqual
(
parseGitmodules
(
''
),
[]);
});
test
(
'
sample
'
,
()
=>
{
const
sample
=
`[submodule "deps/spdlog"]
path = deps/spdlog
url = https://github.com/gabime/spdlog.git
`
;
assert
.
deepEqual
(
parseGitmodules
(
sample
),
[
{
name
:
'
deps/spdlog
'
,
path
:
'
deps/spdlog
'
,
url
:
'
https://github.com/gabime/spdlog.git
'
}
]);
});
test
(
'
big
'
,
()
=>
{
const
sample
=
`[submodule "deps/spdlog"]
path = deps/spdlog
url = https://github.com/gabime/spdlog.git
[submodule "deps/spdlog2"]
path = deps/spdlog2
url = https://github.com/gabime/spdlog.git
[submodule "deps/spdlog3"]
path = deps/spdlog3
url = https://github.com/gabime/spdlog.git
[submodule "deps/spdlog4"]
path = deps/spdlog4
url = https://github.com/gabime/spdlog4.git
`
;
assert
.
deepEqual
(
parseGitmodules
(
sample
),
[
{
name
:
'
deps/spdlog
'
,
path
:
'
deps/spdlog
'
,
url
:
'
https://github.com/gabime/spdlog.git
'
},
{
name
:
'
deps/spdlog2
'
,
path
:
'
deps/spdlog2
'
,
url
:
'
https://github.com/gabime/spdlog.git
'
},
{
name
:
'
deps/spdlog3
'
,
path
:
'
deps/spdlog3
'
,
url
:
'
https://github.com/gabime/spdlog.git
'
},
{
name
:
'
deps/spdlog4
'
,
path
:
'
deps/spdlog4
'
,
url
:
'
https://github.com/gabime/spdlog4.git
'
}
]);
});
});
});
\ No newline at end of file
extensions/git/src/uri.ts
浏览文件 @
1ab3fd8f
...
...
@@ -7,20 +7,45 @@
import
{
Uri
}
from
'
vscode
'
;
export
function
fromGitUri
(
uri
:
Uri
):
{
path
:
string
;
ref
:
string
;
}
{
export
interface
GitUriParams
{
path
:
string
;
ref
:
string
;
submoduleOf
?:
string
;
}
export
function
fromGitUri
(
uri
:
Uri
):
GitUriParams
{
return
JSON
.
parse
(
uri
.
query
);
}
export
interface
GitUriOptions
{
replaceFileExtension
?:
boolean
;
submoduleOf
?:
string
;
}
// As a mitigation for extensions like ESLint showing warnings and errors
// for git URIs, let's change the file extension of these uris to .git,
// when `replaceFileExtension` is true.
export
function
toGitUri
(
uri
:
Uri
,
ref
:
string
,
replaceFileExtension
=
false
):
Uri
{
export
function
toGitUri
(
uri
:
Uri
,
ref
:
string
,
options
:
GitUriOptions
=
{}):
Uri
{
const
params
:
GitUriParams
=
{
path
:
uri
.
fsPath
,
ref
};
if
(
options
.
submoduleOf
)
{
params
.
submoduleOf
=
options
.
submoduleOf
;
}
let
path
=
uri
.
path
;
if
(
options
.
replaceFileExtension
)
{
path
=
path
+
`
${
path
}
.git`
;
}
else
if
(
options
.
submoduleOf
)
{
path
=
path
+
`
${
path
}
.diff`
;
}
return
uri
.
with
({
scheme
:
'
git
'
,
path
:
replaceFileExtension
?
`
${
uri
.
path
}
.git`
:
uri
.
path
,
query
:
JSON
.
stringify
({
path
:
uri
.
fsPath
,
ref
})
path
,
query
:
JSON
.
stringify
(
params
)
});
}
\ No newline at end of file
extensions/git/src/util.ts
浏览文件 @
1ab3fd8f
...
...
@@ -126,6 +126,10 @@ export function groupBy<T>(arr: T[], fn: (el: T) => string): { [key: string]: T[
},
Object
.
create
(
null
));
}
export
function
denodeify
<
A
,
B
,
C
,
R
>
(
fn
:
Function
):
(
a
:
A
,
b
:
B
,
c
:
C
)
=>
Promise
<
R
>
;
export
function
denodeify
<
A
,
B
,
R
>
(
fn
:
Function
):
(
a
:
A
,
b
:
B
)
=>
Promise
<
R
>
;
export
function
denodeify
<
A
,
R
>
(
fn
:
Function
):
(
a
:
A
)
=>
Promise
<
R
>
;
export
function
denodeify
<
R
>
(
fn
:
Function
):
(...
args
:
any
[])
=>
Promise
<
R
>
;
export
function
denodeify
<
R
>
(
fn
:
Function
):
(...
args
:
any
[])
=>
Promise
<
R
>
{
return
(...
args
)
=>
new
Promise
<
R
>
((
c
,
e
)
=>
fn
(...
args
,
(
err
:
any
,
r
:
any
)
=>
err
?
e
(
err
)
:
c
(
r
)));
}
...
...
extensions/gitsyntax/OSSREADME.json
浏览文件 @
1ab3fd8f
//
ATTENTION
-
THIS
DIRECTORY
CONTAINS
THIRD
PARTY
OPEN
SOURCE
MATERIALS:
[{
"name"
:
"textmate/git.tmbundle"
,
"version"
:
"0.0.0"
,
"license"
:
"MIT"
,
"repositoryURL"
:
"https://github.com/textmate/git.tmbundle"
,
"licenseDetail"
:
[
"Copyright (c) 2008 Tim Harper"
,
""
,
"Permission is hereby granted, free of charge, to any person obtaining"
,
"a copy of this software and associated documentation files (the
\"
"
,
"Software
\"
), to deal in the Software without restriction, including"
,
"without limitation the rights to use, copy, modify, merge, publish,"
,
"distribute, sublicense, and/or sell copies of the Software, and to"
,
"permit persons to whom the Software is furnished to do so, subject to"
,
"the following conditions:"
,
""
,
"The above copyright notice and this permission notice shall be"
,
"included in all copies or substantial portions of the Software."
,
""
,
"THE SOFTWARE IS PROVIDED
\"
AS IS
\"
, WITHOUT WARRANTY OF ANY KIND,"
,
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"
,
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND"
,
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
,
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION"
,
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"
,
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
]
}]
\ No newline at end of file
[
{
"name"
:
"textmate/git.tmbundle"
,
"version"
:
"0.0.0"
,
"license"
:
"MIT"
,
"repositoryURL"
:
"https://github.com/textmate/git.tmbundle"
,
"licenseDetail"
:
[
"Copyright (c) 2008 Tim Harper"
,
""
,
"Permission is hereby granted, free of charge, to any person obtaining"
,
"a copy of this software and associated documentation files (the
\"
"
,
"Software
\"
), to deal in the Software without restriction, including"
,
"without limitation the rights to use, copy, modify, merge, publish,"
,
"distribute, sublicense, and/or sell copies of the Software, and to"
,
"permit persons to whom the Software is furnished to do so, subject to"
,
"the following conditions:"
,
""
,
"The above copyright notice and this permission notice shall be"
,
"included in all copies or substantial portions of the Software."
,
""
,
"THE SOFTWARE IS PROVIDED
\"
AS IS
\"
, WITHOUT WARRANTY OF ANY KIND,"
,
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"
,
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND"
,
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
,
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION"
,
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION"
,
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
]
},
{
"name"
:
"textmate/diff.tmbundle"
,
"version"
:
"0.0.0"
,
"repositoryURL"
:
"https://github.com/textmate/diff.tmbundle"
,
"licenseDetail"
:
[
"Permission to copy, use, modify, sell and distribute this"
,
"software is granted. This software is provided
\"
as is
\"
without"
,
"express or implied warranty, and with no claim as to its"
,
"suitability for any purpose."
]
}
]
\ No newline at end of file
extensions/gitsyntax/diff.language-configuration.json
0 → 100644
浏览文件 @
1ab3fd8f
{
"comments"
:
{
"lineComment"
:
"#"
,
"blockComment"
:
[
"#"
,
" "
]
},
"brackets"
:
[
[
"{"
,
"}"
],
[
"["
,
"]"
],
[
"("
,
")"
]
]
}
\ No newline at end of file
extensions/gitsyntax/package.json
浏览文件 @
1ab3fd8f
...
...
@@ -37,6 +37,19 @@
"git-rebase-todo"
],
"configuration"
:
"./git-rebase.language-configuration.json"
},
{
"id"
:
"diff"
,
"aliases"
:
[
"Diff"
,
"diff"
],
"extensions"
:
[
".patch"
,
".diff"
,
".rej"
],
"configuration"
:
"./diff.language-configuration.json"
}
],
"grammars"
:
[
...
...
@@ -49,12 +62,19 @@
"language"
:
"git-rebase"
,
"scopeName"
:
"text.git-rebase"
,
"path"
:
"./syntaxes/git-rebase.tmLanguage.json"
},
{
"language"
:
"diff"
,
"scopeName"
:
"source.diff"
,
"path"
:
"./syntaxes/diff.tmLanguage"
}
],
"configurationDefaults"
:
{
"[git-commit]"
:
{
"editor.rulers"
:
[
72
]
}
}
"[git-commit]"
:
{
"editor.rulers"
:
[
72
]
}
}
}
}
\ No newline at end of file
extensions/gitsyntax/syntaxes/diff.tmLanguage
0 → 100644
浏览文件 @
1ab3fd8f
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist
version=
"1.0"
>
<dict>
<key>
fileTypes
</key>
<array>
<string>
patch
</string>
<string>
diff
</string>
<string>
rej
</string>
</array>
<key>
firstLineMatch
</key>
<string>
(?x)^
(===\ modified\ file
|==== \s* // .+ \s - \s .+ \s+ ====
|Index:\
|---\ [^%\n]
|\*\*\*.*\d{4}\s*$
|\d+(,\d+)* (a|d|c) \d+(,\d+)* $
|diff\ --git\
|commit\ [0-9a-f]{40}$
)
</string>
<key>
keyEquivalent
</key>
<string>
^~D
</string>
<key>
name
</key>
<string>
Diff
</string>
<key>
patterns
</key>
<array>
<dict>
<key>
captures
</key>
<dict>
<key>
1
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.separator.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^((\*{15})|(={67})|(-{3}))$\n?
</string>
<key>
name
</key>
<string>
meta.separator.diff
</string>
</dict>
<dict>
<key>
match
</key>
<string>
^\d+(,\d+)*(a|d|c)\d+(,\d+)*$\n?
</string>
<key>
name
</key>
<string>
meta.diff.range.normal
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
1
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.range.diff
</string>
</dict>
<key>
2
</key>
<dict>
<key>
name
</key>
<string>
meta.toc-list.line-number.diff
</string>
</dict>
<key>
3
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.range.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^(@@)\s*(.+?)\s*(@@)($\n?)?
</string>
<key>
name
</key>
<string>
meta.diff.range.unified
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
3
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.range.diff
</string>
</dict>
<key>
4
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.range.diff
</string>
</dict>
<key>
6
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.range.diff
</string>
</dict>
<key>
7
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.range.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^(((\-{3}) .+ (\-{4}))|((\*{3}) .+ (\*{4})))$\n?
</string>
<key>
name
</key>
<string>
meta.diff.range.context
</string>
</dict>
<dict>
<key>
match
</key>
<string>
^diff --git a/.*$\n?
</string>
<key>
name
</key>
<string>
meta.diff.header.git
</string>
</dict>
<dict>
<key>
match
</key>
<string>
^diff (-|\S+\s+\S+).*$\n?
</string>
<key>
name
</key>
<string>
meta.diff.header.command
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
4
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.from-file.diff
</string>
</dict>
<key>
6
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.from-file.diff
</string>
</dict>
<key>
7
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.from-file.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
(^(((-{3}) .+)|((\*{3}) .+))$\n?|^(={4}) .+(?= - ))
</string>
<key>
name
</key>
<string>
meta.diff.header.from-file
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
2
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.to-file.diff
</string>
</dict>
<key>
3
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.to-file.diff
</string>
</dict>
<key>
4
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.to-file.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
(^(\+{3}) .+$\n?| (-) .* (={4})$\n?)
</string>
<key>
name
</key>
<string>
meta.diff.header.to-file
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
3
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.inserted.diff
</string>
</dict>
<key>
6
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.inserted.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^(((
>
)( .*)?)|((\+).*))$\n?
</string>
<key>
name
</key>
<string>
markup.inserted.diff
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
1
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.changed.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^(!).*$\n?
</string>
<key>
name
</key>
<string>
markup.changed.diff
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
3
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.deleted.diff
</string>
</dict>
<key>
6
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.deleted.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^(((
<
)( .*)?)|((-).*))$\n?
</string>
<key>
name
</key>
<string>
markup.deleted.diff
</string>
</dict>
<dict>
<key>
begin
</key>
<string>
^(#)
</string>
<key>
captures
</key>
<dict>
<key>
1
</key>
<dict>
<key>
name
</key>
<string>
punctuation.definition.comment.diff
</string>
</dict>
</dict>
<key>
comment
</key>
<string>
Git produces unified diffs with embedded comments"
</string>
<key>
end
</key>
<string>
\n
</string>
<key>
name
</key>
<string>
comment.line.number-sign.diff
</string>
</dict>
<dict>
<key>
match
</key>
<string>
^index [0-9a-f]{7,40}\.\.[0-9a-f]{7,40}.*$\n?
</string>
<key>
name
</key>
<string>
meta.diff.index.git
</string>
</dict>
<dict>
<key>
captures
</key>
<dict>
<key>
1
</key>
<dict>
<key>
name
</key>
<string>
punctuation.separator.key-value.diff
</string>
</dict>
<key>
2
</key>
<dict>
<key>
name
</key>
<string>
meta.toc-list.file-name.diff
</string>
</dict>
</dict>
<key>
match
</key>
<string>
^Index(:) (.+)$\n?
</string>
<key>
name
</key>
<string>
meta.diff.index
</string>
</dict>
<dict>
<key>
match
</key>
<string>
^Only in .*: .*$\n?
</string>
<key>
name
</key>
<string>
meta.diff.only-in
</string>
</dict>
</array>
<key>
scopeName
</key>
<string>
source.diff
</string>
<key>
uuid
</key>
<string>
7E848FF4-708E-11D9-97B4-0011242E4184
</string>
</dict>
</plist>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录