Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
3af429fd
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3af429fd
编写于
1月 17, 2017
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
git: improve fs events reaction
上级
4e64aa3e
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
133 addition
and
133 deletion
+133
-133
extensions/git/src/commands.ts
extensions/git/src/commands.ts
+1
-1
extensions/git/src/main.ts
extensions/git/src/main.ts
+2
-27
extensions/git/src/model.ts
extensions/git/src/model.ts
+107
-104
extensions/git/src/scmProvider.ts
extensions/git/src/scmProvider.ts
+0
-1
extensions/git/src/watch.ts
extensions/git/src/watch.ts
+23
-0
未找到文件。
extensions/git/src/commands.ts
浏览文件 @
3af429fd
...
...
@@ -126,7 +126,7 @@ export class CommandCenter {
@
CommandCenter
.
Command
(
'
git.refresh
'
)
@
CommandCenter
.
CatchErrors
async
refresh
():
Promise
<
void
>
{
await
this
.
model
.
update
();
await
this
.
model
.
status
();
}
@
CommandCenter
.
Command
(
'
git.openChange
'
)
...
...
extensions/git/src/main.ts
浏览文件 @
3af429fd
...
...
@@ -5,44 +5,19 @@
'
use strict
'
;
import
{
ExtensionContext
,
workspace
,
Uri
,
window
,
Disposable
,
Event
}
from
'
vscode
'
;
import
{
ExtensionContext
,
workspace
,
window
,
Disposable
}
from
'
vscode
'
;
import
{
findGit
,
Git
}
from
'
./git
'
;
import
{
Model
}
from
'
./model
'
;
import
{
GitSCMProvider
}
from
'
./scmProvider
'
;
import
{
CommandCenter
}
from
'
./commands
'
;
import
{
CheckoutStatusBar
,
SyncStatusBar
}
from
'
./statusbar
'
;
import
{
filterEvent
,
anyEvent
,
throttle
}
from
'
./util
'
;
import
{
filterEvent
,
anyEvent
}
from
'
./util
'
;
import
{
GitContentProvider
}
from
'
./contentProvider
'
;
import
{
AutoFetcher
}
from
'
./autofetch
'
;
import
*
as
nls
from
'
vscode-nls
'
;
import
{
decorate
,
debounce
}
from
'
core-decorators
'
;
nls
.
config
();
class
Watcher
{
private
listener
:
Disposable
;
constructor
(
private
model
:
Model
,
onWorkspaceChange
:
Event
<
Uri
>
)
{
this
.
listener
=
onWorkspaceChange
(
this
.
eventuallyUpdateModel
,
this
);
}
@
debounce
(
1000
)
private
eventuallyUpdateModel
():
void
{
this
.
updateModelAndWait
();
}
@
decorate
(
throttle
)
private
async
updateModelAndWait
():
Promise
<
void
>
{
await
this
.
model
.
update
();
await
new
Promise
(
c
=>
setTimeout
(
c
,
8000
));
}
dispose
():
void
{
this
.
listener
.
dispose
();
}
}
async
function
init
(
disposables
:
Disposable
[]):
Promise
<
void
>
{
const
rootPath
=
workspace
.
rootPath
;
...
...
extensions/git/src/model.ts
浏览文件 @
3af429fd
...
...
@@ -7,7 +7,8 @@
import
{
Uri
,
EventEmitter
,
Event
,
SCMResource
,
SCMResourceDecorations
,
SCMResourceGroup
,
Disposable
}
from
'
vscode
'
;
import
{
Repository
,
IRef
,
IBranch
,
IRemote
,
IPushOptions
}
from
'
./git
'
;
import
{
throttle
,
anyEvent
,
eventToPromise
}
from
'
./util
'
;
import
{
throttle
,
anyEvent
,
eventToPromise
,
filterEvent
,
mapEvent
}
from
'
./util
'
;
import
{
watch
}
from
'
./watch
'
;
import
{
decorate
,
memoize
,
debounce
}
from
'
core-decorators
'
;
import
*
as
path
from
'
path
'
;
...
...
@@ -242,7 +243,22 @@ export class Model {
private
repository
:
Repository
,
onWorkspaceChange
:
Event
<
Uri
>
)
{
onWorkspaceChange
(
this
.
onWorkspaceChange
,
this
,
this
.
disposables
);
/* We use the native Node `watch` for faster, non debounced events.
* That way we hopefully get the events during the operations we're
* performing, thus sparing useless `git status` calls to refresh
* the model's state.
*/
const
gitPath
=
path
.
join
(
_repositoryRoot
,
'
.git
'
);
const
{
event
,
disposable
}
=
watch
(
gitPath
);
const
onGitChange
=
mapEvent
(
event
,
({
filename
})
=>
Uri
.
file
(
path
.
join
(
gitPath
,
filename
)));
const
onRelevantGitChange
=
filterEvent
(
onGitChange
,
uri
=>
!
/
\/\.
git
\/
index
\.
lock$/
.
test
(
uri
.
fsPath
));
onRelevantGitChange
(
this
.
onFSChange
,
this
,
this
.
disposables
);
this
.
disposables
.
push
(
disposable
);
const
onNonGitChange
=
filterEvent
(
onWorkspaceChange
,
uri
=>
!
/
\/\.
git
\/
/
.
test
(
uri
.
fsPath
));
onNonGitChange
(
this
.
onFSChange
,
this
,
this
.
disposables
);
this
.
status
();
}
get
repositoryRoot
():
string
{
...
...
@@ -265,90 +281,18 @@ export class Model {
}
@
decorate
(
throttle
)
async
update
():
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Status
,
async
()
=>
{
const
status
=
await
this
.
repository
.
getStatus
();
let
HEAD
:
IBranch
|
undefined
;
try
{
HEAD
=
await
this
.
repository
.
getHEAD
();
if
(
HEAD
.
name
)
{
try
{
HEAD
=
await
this
.
repository
.
getBranch
(
HEAD
.
name
);
}
catch
(
err
)
{
// noop
}
}
}
catch
(
err
)
{
// noop
}
const
[
refs
,
remotes
]
=
await
Promise
.
all
([
this
.
repository
.
getRefs
(),
this
.
repository
.
getRemotes
()]);
this
.
_HEAD
=
HEAD
;
this
.
_refs
=
refs
;
this
.
_remotes
=
remotes
;
const
index
:
Resource
[]
=
[];
const
workingTree
:
Resource
[]
=
[];
const
merge
:
Resource
[]
=
[];
status
.
forEach
(
raw
=>
{
const
uri
=
Uri
.
file
(
path
.
join
(
this
.
repositoryRoot
,
raw
.
path
));
switch
(
raw
.
x
+
raw
.
y
)
{
case
'
??
'
:
return
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
UNTRACKED
));
case
'
!!
'
:
return
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
IGNORED
));
case
'
DD
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
BOTH_DELETED
));
case
'
AU
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
ADDED_BY_US
));
case
'
UD
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
DELETED_BY_THEM
));
case
'
UA
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
ADDED_BY_THEM
));
case
'
DU
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
DELETED_BY_US
));
case
'
AA
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
BOTH_ADDED
));
case
'
UU
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
BOTH_MODIFIED
));
}
let
isModifiedInIndex
=
false
;
switch
(
raw
.
x
)
{
case
'
M
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_MODIFIED
));
isModifiedInIndex
=
true
;
break
;
case
'
A
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_ADDED
));
break
;
case
'
D
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_DELETED
));
break
;
case
'
R
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_RENAMED
/*, raw.rename*/
));
break
;
case
'
C
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_COPIED
));
break
;
}
switch
(
raw
.
y
)
{
case
'
M
'
:
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
MODIFIED
/*, raw.rename*/
));
break
;
case
'
D
'
:
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
DELETED
/*, raw.rename*/
));
break
;
}
});
this
.
_mergeGroup
=
new
MergeGroup
(
merge
);
this
.
_indexGroup
=
new
IndexGroup
(
index
);
this
.
_workingTreeGroup
=
new
WorkingTreeGroup
(
workingTree
);
this
.
_onDidChange
.
fire
(
this
.
resources
);
});
async
status
():
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Status
);
}
@
decorate
(
throttle
)
async
stage
(...
resources
:
Resource
[]):
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Stage
,
async
()
=>
{
const
paths
=
resources
.
map
(
r
=>
r
.
uri
.
fsPath
);
await
this
.
repository
.
add
(
paths
);
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Stage
,
()
=>
this
.
repository
.
add
(
resources
.
map
(
r
=>
r
.
uri
.
fsPath
)));
}
@
decorate
(
throttle
)
async
unstage
(...
resources
:
Resource
[]):
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Unstage
,
async
()
=>
{
const
paths
=
resources
.
map
(
r
=>
r
.
uri
.
fsPath
);
await
this
.
repository
.
revertFiles
(
'
HEAD
'
,
paths
);
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Unstage
,
()
=>
this
.
repository
.
revertFiles
(
'
HEAD
'
,
resources
.
map
(
r
=>
r
.
uri
.
fsPath
)));
}
@
decorate
(
throttle
)
...
...
@@ -359,7 +303,6 @@ export class Model {
}
await
this
.
repository
.
commit
(
message
,
opts
);
await
this
.
update
();
});
}
...
...
@@ -393,72 +336,132 @@ export class Model {
}
await
Promise
.
all
(
promises
);
await
this
.
update
();
});
}
@
decorate
(
throttle
)
async
branch
(
name
:
string
):
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Branch
,
async
()
=>
{
await
this
.
repository
.
branch
(
name
,
true
);
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Branch
,
()
=>
this
.
repository
.
branch
(
name
,
true
));
}
@
decorate
(
throttle
)
async
checkout
(
treeish
:
string
):
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Checkout
,
async
()
=>
{
await
this
.
repository
.
checkout
(
treeish
,
[]);
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Checkout
,
()
=>
this
.
repository
.
checkout
(
treeish
,
[]));
}
@
decorate
(
throttle
)
async
fetch
():
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Fetch
,
async
()
=>
{
await
this
.
repository
.
fetch
();
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Fetch
,
()
=>
this
.
repository
.
fetch
());
}
@
decorate
(
throttle
)
async
sync
():
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Sync
,
async
()
=>
{
await
this
.
repository
.
sync
();
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Sync
,
()
=>
this
.
repository
.
sync
());
}
@
decorate
(
throttle
)
async
push
(
remote
?:
string
,
name
?:
string
,
options
?:
IPushOptions
):
Promise
<
void
>
{
await
this
.
run
(
Operation
.
Push
,
async
()
=>
{
await
this
.
repository
.
push
(
remote
,
name
,
options
);
await
this
.
update
();
});
await
this
.
run
(
Operation
.
Push
,
()
=>
this
.
repository
.
push
(
remote
,
name
,
options
));
}
private
async
run
(
operation
:
Operation
,
fn
:
()
=>
Promise
<
void
>
):
Promise
<
void
>
{
private
async
run
(
operation
:
Operation
,
fn
:
()
=>
Promise
<
void
>
=
()
=>
Promise
.
resolve
()
):
Promise
<
void
>
{
this
.
_operations
=
this
.
_operations
.
start
(
operation
);
this
.
_onRunOperation
.
fire
(
operation
);
try
{
await
fn
();
await
this
.
update
();
}
finally
{
this
.
_operations
=
this
.
_operations
.
end
(
operation
);
this
.
_onDidRunOperation
.
fire
(
operation
);
}
}
@
decorate
(
throttle
)
private
async
update
():
Promise
<
void
>
{
const
status
=
await
this
.
repository
.
getStatus
();
let
HEAD
:
IBranch
|
undefined
;
try
{
HEAD
=
await
this
.
repository
.
getHEAD
();
if
(
HEAD
.
name
)
{
try
{
HEAD
=
await
this
.
repository
.
getBranch
(
HEAD
.
name
);
}
catch
(
err
)
{
// noop
}
}
}
catch
(
err
)
{
// noop
}
const
[
refs
,
remotes
]
=
await
Promise
.
all
([
this
.
repository
.
getRefs
(),
this
.
repository
.
getRemotes
()]);
this
.
_HEAD
=
HEAD
;
this
.
_refs
=
refs
;
this
.
_remotes
=
remotes
;
const
index
:
Resource
[]
=
[];
const
workingTree
:
Resource
[]
=
[];
const
merge
:
Resource
[]
=
[];
status
.
forEach
(
raw
=>
{
const
uri
=
Uri
.
file
(
path
.
join
(
this
.
repositoryRoot
,
raw
.
path
));
switch
(
raw
.
x
+
raw
.
y
)
{
case
'
??
'
:
return
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
UNTRACKED
));
case
'
!!
'
:
return
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
IGNORED
));
case
'
DD
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
BOTH_DELETED
));
case
'
AU
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
ADDED_BY_US
));
case
'
UD
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
DELETED_BY_THEM
));
case
'
UA
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
ADDED_BY_THEM
));
case
'
DU
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
DELETED_BY_US
));
case
'
AA
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
BOTH_ADDED
));
case
'
UU
'
:
return
merge
.
push
(
new
Resource
(
uri
,
Status
.
BOTH_MODIFIED
));
}
let
isModifiedInIndex
=
false
;
switch
(
raw
.
x
)
{
case
'
M
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_MODIFIED
));
isModifiedInIndex
=
true
;
break
;
case
'
A
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_ADDED
));
break
;
case
'
D
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_DELETED
));
break
;
case
'
R
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_RENAMED
/*, raw.rename*/
));
break
;
case
'
C
'
:
index
.
push
(
new
Resource
(
uri
,
Status
.
INDEX_COPIED
));
break
;
}
switch
(
raw
.
y
)
{
case
'
M
'
:
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
MODIFIED
/*, raw.rename*/
));
break
;
case
'
D
'
:
workingTree
.
push
(
new
Resource
(
uri
,
Status
.
DELETED
/*, raw.rename*/
));
break
;
}
});
this
.
_mergeGroup
=
new
MergeGroup
(
merge
);
this
.
_indexGroup
=
new
IndexGroup
(
index
);
this
.
_workingTreeGroup
=
new
WorkingTreeGroup
(
workingTree
);
this
.
_onDidChange
.
fire
(
this
.
resources
);
}
private
onFSChange
(
uri
:
Uri
):
void
{
if
(
!
this
.
operations
.
isIdle
())
{
return
;
}
this
.
eventuallyUpdateWhenIdleAndWait
();
}
@
debounce
(
1000
)
private
onWorkspaceChange
():
void
{
private
eventuallyUpdateWhenIdleAndWait
():
void
{
this
.
updateWhenIdleAndWait
();
}
@
decorate
(
throttle
)
private
async
updateWhenIdleAndWait
():
Promise
<
void
>
{
await
this
.
whenIdle
();
await
this
.
update
();
await
new
Promise
(
c
=>
setTimeout
(
c
,
7
000
));
await
this
.
status
();
await
new
Promise
(
c
=>
setTimeout
(
c
,
5
000
));
}
private
async
whenIdle
():
Promise
<
void
>
{
...
...
extensions/git/src/scmProvider.ts
浏览文件 @
3af429fd
...
...
@@ -18,7 +18,6 @@ export class GitSCMProvider implements SCMProvider {
get
label
():
string
{
return
'
Git
'
;
}
constructor
(
private
model
:
Model
,
private
commandCenter
:
CommandCenter
)
{
model
.
update
();
scm
.
registerSCMProvider
(
'
git
'
,
this
);
}
...
...
extensions/git/src/watch.ts
0 → 100644
浏览文件 @
3af429fd
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
EventEmitter
,
Event
,
Disposable
}
from
'
vscode
'
;
import
*
as
fs
from
'
fs
'
;
export
interface
FSEvent
{
eventType
:
string
;
filename
:
string
;
}
export
function
watch
(
path
:
string
):
{
event
:
Event
<
FSEvent
>
;
disposable
:
Disposable
;
}
{
const
emitter
=
new
EventEmitter
<
FSEvent
>
();
const
event
=
emitter
.
event
;
const
watcher
=
fs
.
watch
(
path
,
(
eventType
,
filename
)
=>
emitter
.
fire
({
eventType
,
filename
}));
const
disposable
=
new
Disposable
(()
=>
watcher
.
close
());
return
{
event
,
disposable
};
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录