Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
9e457a6c
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,发现更多精彩内容 >>
提交
9e457a6c
编写于
7月 16, 2020
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
#100346 introduce merge state on a resource. Do not apply automatically.
上级
80a33109
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
300 addition
and
130 deletion
+300
-130
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
+66
-58
src/vs/platform/userDataSync/common/userDataSync.ts
src/vs/platform/userDataSync/common/userDataSync.ts
+15
-7
src/vs/platform/userDataSync/common/userDataSyncIpc.ts
src/vs/platform/userDataSync/common/userDataSyncIpc.ts
+2
-1
src/vs/platform/userDataSync/common/userDataSyncService.ts
src/vs/platform/userDataSync/common/userDataSyncService.ts
+21
-25
src/vs/platform/userDataSync/test/common/snippetsSync.test.ts
...vs/platform/userDataSync/test/common/snippetsSync.test.ts
+114
-18
src/vs/platform/userDataSync/test/common/synchronizer.test.ts
...vs/platform/userDataSync/test/common/synchronizer.test.ts
+64
-7
src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts
...vs/workbench/contrib/userDataSync/browser/userDataSync.ts
+3
-3
src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts
...ices/userDataSync/browser/userDataSyncWorkbenchService.ts
+7
-8
src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts
...ices/userDataSync/electron-browser/userDataSyncService.ts
+8
-3
未找到文件。
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
浏览文件 @
9e457a6c
...
...
@@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri';
import
{
SyncResource
,
SyncStatus
,
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
UserDataSyncError
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
IUserDataSyncResourceEnablementService
,
IUserDataSyncBackupStoreService
,
ISyncResourceHandle
,
USER_DATA_SYNC_SCHEME
,
ISyncResourcePreview
as
IBaseSyncResourcePreview
,
IUserDataManifest
,
ISyncData
,
IRemoteUserData
,
PREVIEW_DIR_NAME
,
IResourcePreview
as
IBaseResourcePreview
,
Change
IUserDataManifest
,
ISyncData
,
IRemoteUserData
,
PREVIEW_DIR_NAME
,
IResourcePreview
as
IBaseResourcePreview
,
Change
,
MergeState
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
joinPath
,
dirname
,
isEqual
,
basename
}
from
'
vs/base/common/resources
'
;
...
...
@@ -58,10 +58,10 @@ export interface IMergableResourcePreview extends IBaseResourcePreview {
readonly
localContent
:
string
|
null
;
readonly
previewContent
:
string
|
null
;
readonly
hasConflicts
:
boolean
;
merge
d
:
boolean
;
merge
State
:
MergeState
;
}
export
type
IResourcePreview
=
Omit
<
IMergableResourcePreview
,
'
merge
d
'
>
;
export
type
IResourcePreview
=
Omit
<
IMergableResourcePreview
,
'
merge
State
'
>
;
export
interface
ISyncResourcePreview
extends
IBaseSyncResourcePreview
{
readonly
remoteUserData
:
IRemoteUserData
;
...
...
@@ -217,6 +217,19 @@ export abstract class AbstractSynchroniser extends Disposable {
return
this
.
_sync
(
manifest
,
false
,
headers
);
}
async
apply
(
force
:
boolean
,
headers
:
IHeaders
=
{}):
Promise
<
ISyncResourcePreview
|
null
>
{
try
{
this
.
syncHeaders
=
{
...
headers
};
const
status
=
await
this
.
doApply
(
force
);
this
.
setStatus
(
status
);
return
this
.
syncPreviewPromise
;
}
finally
{
this
.
syncHeaders
=
{};
}
}
private
async
_sync
(
manifest
:
IUserDataManifest
|
null
,
apply
:
boolean
,
headers
:
IHeaders
):
Promise
<
ISyncResourcePreview
|
null
>
{
try
{
this
.
syncHeaders
=
{
...
headers
};
...
...
@@ -350,14 +363,18 @@ export abstract class AbstractSynchroniser extends Disposable {
this
.
syncPreviewPromise
=
createCancelablePromise
(
token
=>
this
.
doGenerateSyncResourcePreview
(
remoteUserData
,
lastSyncUserData
,
apply
,
token
));
}
const
preview
=
await
this
.
syncPreviewPromise
;
this
.
updateConflicts
(
preview
.
resourcePreviews
);
if
(
preview
.
resourcePreviews
.
some
(({
mergeState
})
=>
mergeState
===
MergeState
.
Conflict
))
{
return
SyncStatus
.
HasConflicts
;
}
if
(
apply
)
{
const
preview
=
await
this
.
syncPreviewPromise
;
const
newConflicts
=
preview
.
resourcePreviews
.
filter
(({
hasConflicts
})
=>
hasConflicts
);
return
await
this
.
updateConflictsAndApply
(
newConflicts
,
false
);
}
else
{
return
SyncStatus
.
Syncing
;
return
await
this
.
doApply
(
false
);
}
return
SyncStatus
.
Syncing
;
}
catch
(
error
)
{
// reset preview on error
...
...
@@ -367,76 +384,63 @@ export abstract class AbstractSynchroniser extends Disposable {
}
}
async
accept
PreviewContent
(
resource
:
URI
,
content
:
string
,
force
:
boolean
,
headers
:
IHeaders
=
{}
):
Promise
<
ISyncResourcePreview
|
null
>
{
async
accept
(
resource
:
URI
,
content
:
string
):
Promise
<
ISyncResourcePreview
|
null
>
{
if
(
!
this
.
syncPreviewPromise
)
{
return
null
;
}
try
{
this
.
syncHeaders
=
{
...
headers
};
const
preview
=
await
this
.
syncPreviewPromise
;
this
.
syncPreviewPromise
=
createCancelablePromise
(
token
=>
this
.
updateSyncResourcePreviewContent
(
preview
,
resource
,
content
,
token
));
return
this
.
merge
(
resource
,
force
,
headers
);
}
finally
{
this
.
syncHeaders
=
{};
let
preview
=
await
this
.
syncPreviewPromise
;
this
.
syncPreviewPromise
=
createCancelablePromise
(
token
=>
this
.
updateSyncResourcePreviewContent
(
preview
,
resource
,
content
,
token
));
preview
=
await
this
.
syncPreviewPromise
;
this
.
updateConflicts
(
preview
.
resourcePreviews
);
if
(
preview
.
resourcePreviews
.
some
(({
mergeState
})
=>
mergeState
===
MergeState
.
Conflict
))
{
this
.
setStatus
(
SyncStatus
.
HasConflicts
);
}
else
{
this
.
setStatus
(
SyncStatus
.
Syncing
);
}
return
preview
;
}
async
merge
(
resource
:
URI
,
force
:
boolean
,
headers
:
IHeaders
=
{}
):
Promise
<
ISyncResourcePreview
|
null
>
{
async
merge
(
resource
:
URI
):
Promise
<
ISyncResourcePreview
|
null
>
{
if
(
!
this
.
syncPreviewPromise
)
{
return
null
;
}
try
{
this
.
syncHeaders
=
{
...
headers
};
const
preview
=
await
this
.
syncPreviewPromise
;
const
resourcePreview
=
preview
.
resourcePreviews
.
find
(({
localResource
,
remoteResource
,
previewResource
})
=>
isEqual
(
localResource
,
resource
)
||
isEqual
(
remoteResource
,
resource
)
||
isEqual
(
previewResource
,
resource
));
if
(
!
resourcePreview
)
{
return
preview
;
}
/* mark merged */
resourcePreview
.
merged
=
true
;
/* Add or remove the preview from conflicts */
const
newConflicts
=
[...
this
.
_conflicts
];
const
index
=
newConflicts
.
findIndex
(({
localResource
,
remoteResource
,
previewResource
})
=>
isEqual
(
localResource
,
resource
)
||
isEqual
(
remoteResource
,
resource
)
||
isEqual
(
previewResource
,
resource
));
if
(
resourcePreview
.
hasConflicts
)
{
if
(
newConflicts
.
indexOf
(
resourcePreview
)
===
-
1
)
{
newConflicts
.
push
(
resourcePreview
);
}
}
else
{
if
(
index
!==
-
1
)
{
newConflicts
.
splice
(
index
,
1
);
}
}
const
preview
=
await
this
.
syncPreviewPromise
;
const
resourcePreview
=
preview
.
resourcePreviews
.
find
(({
localResource
,
remoteResource
,
previewResource
})
=>
isEqual
(
localResource
,
resource
)
||
isEqual
(
remoteResource
,
resource
)
||
isEqual
(
previewResource
,
resource
));
if
(
!
resourcePreview
)
{
return
preview
;
}
const
status
=
await
this
.
updateConflictsAndApply
(
newConflicts
,
force
);
this
.
setStatus
(
status
);
return
this
.
syncPreviewPromise
;
resourcePreview
.
mergeState
=
resourcePreview
.
hasConflicts
?
MergeState
.
Conflict
:
MergeState
.
Accepted
;
}
finally
{
this
.
syncHeaders
=
{};
this
.
updateConflicts
(
preview
.
resourcePreviews
);
if
(
preview
.
resourcePreviews
.
some
(({
mergeState
})
=>
mergeState
===
MergeState
.
Conflict
))
{
this
.
setStatus
(
SyncStatus
.
HasConflicts
);
}
else
{
this
.
setStatus
(
SyncStatus
.
Syncing
);
}
return
preview
;
}
private
async
updateConflictsAndApply
(
conflicts
:
IMergableResourcePreview
[],
force
:
boolean
):
Promise
<
SyncStatus
>
{
private
async
doApply
(
force
:
boolean
):
Promise
<
SyncStatus
>
{
if
(
!
this
.
syncPreviewPromise
)
{
return
SyncStatus
.
Idle
;
}
const
preview
=
await
this
.
syncPreviewPromise
;
// update conflicts
this
.
updateConflicts
(
conflicts
);
if
(
this
.
_conflicts
.
length
)
{
// check for conflicts
if
(
preview
.
resourcePreviews
.
some
(({
mergeState
})
=>
mergeState
===
MergeState
.
Conflict
))
{
return
SyncStatus
.
HasConflicts
;
}
// check if all are
merg
ed
if
(
preview
.
resourcePreviews
.
some
(
r
=>
!
r
.
merg
ed
))
{
// check if all are
accept
ed
if
(
preview
.
resourcePreviews
.
some
(
({
mergeState
})
=>
mergeState
!==
MergeState
.
Accept
ed
))
{
return
SyncStatus
.
Syncing
;
}
...
...
@@ -459,7 +463,7 @@ export abstract class AbstractSynchroniser extends Disposable {
if
(
index
!==
-
1
)
{
const
resourcePreviews
=
[...
preview
.
resourcePreviews
];
const
resourcePreview
=
await
this
.
updateResourcePreviewContent
(
resourcePreviews
[
index
],
resource
,
previewContent
,
token
);
resourcePreviews
[
index
]
=
{
...
resourcePreview
,
merge
d
:
resourcePreviews
[
index
].
merg
ed
};
resourcePreviews
[
index
]
=
{
...
resourcePreview
,
merge
State
:
MergeState
.
Accept
ed
};
preview
=
{
...
preview
,
resourcePreviews
...
...
@@ -484,7 +488,8 @@ export abstract class AbstractSynchroniser extends Disposable {
}
catch
(
error
)
{
/* Ignore */
}
}
private
updateConflicts
(
conflicts
:
IMergableResourcePreview
[]):
void
{
private
updateConflicts
(
previews
:
IMergableResourcePreview
[]):
void
{
const
conflicts
=
previews
.
filter
(
p
=>
p
.
mergeState
===
MergeState
.
Conflict
);
if
(
!
equals
(
this
.
_conflicts
,
conflicts
,
(
a
,
b
)
=>
isEqual
(
a
.
previewResource
,
b
.
previewResource
)))
{
this
.
_conflicts
=
conflicts
;
this
.
_onDidChangeConflicts
.
fire
(
conflicts
);
...
...
@@ -562,7 +567,7 @@ export abstract class AbstractSynchroniser extends Disposable {
}
catch
(
e
)
{
/* ignore */
}
}
private
async
doGenerateSyncResourcePreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
,
merge
:
boolean
,
token
:
CancellationToken
):
Promise
<
ISyncResourcePreview
>
{
private
async
doGenerateSyncResourcePreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
,
apply
:
boolean
,
token
:
CancellationToken
):
Promise
<
ISyncResourcePreview
>
{
const
machineId
=
await
this
.
currentMachineIdPromise
;
const
isLastSyncFromCurrentMachine
=
!!
remoteUserData
.
syncData
?.
machineId
&&
remoteUserData
.
syncData
.
machineId
===
machineId
;
...
...
@@ -571,9 +576,12 @@ export abstract class AbstractSynchroniser extends Disposable {
const
resourcePreviews
=
await
this
.
generateSyncPreview
(
remoteUserData
,
lastSyncUserDataForPreview
,
token
);
// Mark merge
const
mergableResourcePreviews
=
resourcePreviews
.
map
(
r
=>
({
const
mergableResourcePreviews
=
resourcePreviews
.
map
<
IMergableResourcePreview
>
(
r
=>
({
...
r
,
merged
:
merge
||
(
r
.
localChange
===
Change
.
None
&&
r
.
remoteChange
===
Change
.
None
)
/* Mark previews with no changes as merged */
mergeState
:
r
.
localChange
===
Change
.
None
&&
r
.
remoteChange
===
Change
.
None
?
MergeState
.
Accepted
/* Mark previews with no changes as merged */
:
apply
?
(
r
.
hasConflicts
?
MergeState
.
Conflict
:
MergeState
.
Accepted
)
:
MergeState
.
Preview
}));
return
{
remoteUserData
,
lastSyncUserData
,
resourcePreviews
:
mergableResourcePreviews
,
isLastSyncFromCurrentMachine
};
...
...
src/vs/platform/userDataSync/common/userDataSync.ts
浏览文件 @
9e457a6c
...
...
@@ -317,13 +317,19 @@ export const enum Change {
Deleted
,
}
export
const
enum
MergeState
{
Preview
,
Conflict
,
Accepted
,
}
export
interface
IResourcePreview
{
readonly
remoteResource
:
URI
;
readonly
localResource
:
URI
;
readonly
previewResource
:
URI
;
readonly
localChange
:
Change
;
readonly
remoteChange
:
Change
;
readonly
merge
d
:
boolean
;
readonly
merge
State
:
MergeState
;
}
export
interface
ISyncResourcePreview
{
...
...
@@ -345,18 +351,19 @@ export interface IUserDataSynchroniser {
pull
():
Promise
<
void
>
;
push
():
Promise
<
void
>
;
sync
(
manifest
:
IUserDataManifest
|
null
,
headers
:
IHeaders
):
Promise
<
void
>
;
preview
(
manifest
:
IUserDataManifest
|
null
,
headers
:
IHeaders
):
Promise
<
ISyncResourcePreview
|
null
>
;
replace
(
uri
:
URI
):
Promise
<
boolean
>
;
stop
():
Promise
<
void
>
;
preview
(
manifest
:
IUserDataManifest
|
null
,
headers
:
IHeaders
):
Promise
<
ISyncResourcePreview
|
null
>
;
accept
(
resource
:
URI
,
content
:
string
):
Promise
<
ISyncResourcePreview
|
null
>
;
merge
(
resource
:
URI
):
Promise
<
ISyncResourcePreview
|
null
>
;
apply
(
force
:
boolean
,
headers
:
IHeaders
):
Promise
<
ISyncResourcePreview
|
null
>
;
hasPreviouslySynced
():
Promise
<
boolean
>
;
hasLocalData
():
Promise
<
boolean
>
;
resetLocal
():
Promise
<
void
>
;
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
;
acceptPreviewContent
(
resource
:
URI
,
content
:
string
,
force
:
boolean
,
headers
:
IHeaders
):
Promise
<
ISyncResourcePreview
|
null
>
;
merge
(
resource
:
URI
,
force
:
boolean
,
headers
:
IHeaders
):
Promise
<
ISyncResourcePreview
|
null
>
;
getRemoteSyncResourceHandles
():
Promise
<
ISyncResourceHandle
[]
>
;
getLocalSyncResourceHandles
():
Promise
<
ISyncResourceHandle
[]
>
;
getAssociatedResources
(
syncResourceHandle
:
ISyncResourceHandle
):
Promise
<
{
resource
:
URI
,
comparableResource
?:
URI
}[]
>
;
...
...
@@ -388,7 +395,8 @@ export interface IManualSyncTask extends IDisposable {
readonly
onSynchronizeResources
:
Event
<
[
SyncResource
,
URI
[]][]
>
;
preview
():
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
;
accept
(
uri
:
URI
,
content
:
string
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
;
merge
(
uri
?:
URI
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
;
merge
(
uri
:
URI
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
;
apply
():
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
;
pull
():
Promise
<
void
>
;
push
():
Promise
<
void
>
;
stop
():
Promise
<
void
>
;
...
...
@@ -422,7 +430,7 @@ export interface IUserDataSyncService {
hasLocalData
():
Promise
<
boolean
>
;
hasPreviouslySynced
():
Promise
<
boolean
>
;
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
;
accept
PreviewContent
(
resource
:
SyncResource
,
conflictResource
:
URI
,
content
:
string
):
Promise
<
void
>
;
accept
(
resource
:
SyncResource
,
conflictResource
:
URI
,
content
:
string
,
apply
:
boolean
):
Promise
<
void
>
;
getLocalSyncResourceHandles
(
resource
:
SyncResource
):
Promise
<
ISyncResourceHandle
[]
>
;
getRemoteSyncResourceHandles
(
resource
:
SyncResource
):
Promise
<
ISyncResourceHandle
[]
>
;
...
...
src/vs/platform/userDataSync/common/userDataSyncIpc.ts
浏览文件 @
9e457a6c
...
...
@@ -53,7 +53,7 @@ export class UserDataSyncChannel implements IServerChannel {
case
'
resetLocal
'
:
return
this
.
service
.
resetLocal
();
case
'
hasPreviouslySynced
'
:
return
this
.
service
.
hasPreviouslySynced
();
case
'
hasLocalData
'
:
return
this
.
service
.
hasLocalData
();
case
'
accept
PreviewContent
'
:
return
this
.
service
.
acceptPreviewContent
(
args
[
0
],
URI
.
revive
(
args
[
1
]),
args
[
2
]);
case
'
accept
'
:
return
this
.
service
.
accept
(
args
[
0
],
URI
.
revive
(
args
[
1
]),
args
[
2
],
args
[
3
]);
case
'
resolveContent
'
:
return
this
.
service
.
resolveContent
(
URI
.
revive
(
args
[
0
]));
case
'
getLocalSyncResourceHandles
'
:
return
this
.
service
.
getLocalSyncResourceHandles
(
args
[
0
]);
case
'
getRemoteSyncResourceHandles
'
:
return
this
.
service
.
getRemoteSyncResourceHandles
(
args
[
0
]);
...
...
@@ -87,6 +87,7 @@ class ManualSyncTaskChannel implements IServerChannel {
case
'
preview
'
:
return
this
.
manualSyncTask
.
preview
();
case
'
accept
'
:
return
this
.
manualSyncTask
.
accept
(
URI
.
revive
(
args
[
0
]),
args
[
1
]);
case
'
merge
'
:
return
this
.
manualSyncTask
.
merge
(
URI
.
revive
(
args
[
0
]));
case
'
apply
'
:
return
this
.
manualSyncTask
.
apply
();
case
'
pull
'
:
return
this
.
manualSyncTask
.
pull
();
case
'
push
'
:
return
this
.
manualSyncTask
.
push
();
case
'
stop
'
:
return
this
.
manualSyncTask
.
stop
();
...
...
src/vs/platform/userDataSync/common/userDataSyncService.ts
浏览文件 @
9e457a6c
...
...
@@ -264,10 +264,13 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
}
}
async
accept
PreviewContent
(
syncResource
:
SyncResource
,
resource
:
URI
,
content
:
string
,
executionId
:
string
=
generateUuid
()
):
Promise
<
void
>
{
async
accept
(
syncResource
:
SyncResource
,
resource
:
URI
,
content
:
string
,
apply
:
boolean
):
Promise
<
void
>
{
await
this
.
checkEnablement
();
const
synchroniser
=
this
.
getSynchroniser
(
syncResource
);
await
synchroniser
.
acceptPreviewContent
(
resource
,
content
,
false
,
createSyncHeaders
(
executionId
));
await
synchroniser
.
accept
(
resource
,
content
);
if
(
apply
)
{
await
synchroniser
.
apply
(
false
,
createSyncHeaders
(
generateUuid
()));
}
}
async
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
{
...
...
@@ -461,18 +464,14 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
}
async
accept
(
resource
:
URI
,
content
:
string
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
return
this
.
mergeOrAccept
(
resource
,
(
sychronizer
,
force
)
=>
sychronizer
.
acceptPreviewContent
(
resource
,
content
,
force
,
this
.
syncHeaders
));
return
this
.
mergeOrAccept
(
resource
,
sychronizer
=>
sychronizer
.
accept
(
resource
,
content
));
}
async
merge
(
resource
?:
URI
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
if
(
resource
)
{
return
this
.
mergeOrAccept
(
resource
,
(
sychronizer
,
force
)
=>
sychronizer
.
merge
(
resource
,
force
,
this
.
syncHeaders
));
}
else
{
return
this
.
mergeAll
();
}
async
merge
(
resource
:
URI
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
return
this
.
mergeOrAccept
(
resource
,
sychronizer
=>
sychronizer
.
merge
(
resource
));
}
private
async
mergeOrAccept
(
resource
:
URI
,
mergeOrAccept
:
(
synchroniser
:
IUserDataSynchroniser
,
force
:
boolean
)
=>
Promise
<
ISyncResourcePreview
|
null
>
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
private
async
mergeOrAccept
(
resource
:
URI
,
mergeOrAccept
:
(
synchroniser
:
IUserDataSynchroniser
)
=>
Promise
<
ISyncResourcePreview
|
null
>
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
if
(
!
this
.
previews
)
{
throw
new
Error
(
'
You need to create preview before merging or accepting
'
);
}
...
...
@@ -500,9 +499,7 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
}
const
synchroniser
=
this
.
synchronisers
.
find
(
s
=>
s
.
resource
===
this
.
previews
!
[
index
][
0
])
!
;
/* force only if the resource is local or remote resource */
const
force
=
isEqual
(
resource
,
resourcePreview
.
localResource
)
||
isEqual
(
resource
,
resourcePreview
.
remoteResource
);
const
preview
=
await
mergeOrAccept
(
synchroniser
,
force
);
const
preview
=
await
mergeOrAccept
(
synchroniser
);
preview
?
this
.
previews
.
splice
(
index
,
1
,
this
.
toSyncResourcePreview
(
synchroniser
.
resource
,
preview
))
:
this
.
previews
.
splice
(
index
,
1
);
const
i
=
this
.
synchronizingResources
.
findIndex
(
s
=>
s
[
0
]
===
syncResource
);
...
...
@@ -515,24 +512,21 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
return
this
.
previews
;
}
private
async
mergeAll
():
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
async
apply
():
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
if
(
!
this
.
previews
)
{
throw
new
Error
(
'
You need to create preview before
merg
ing
'
);
throw
new
Error
(
'
You need to create preview before
apply
ing
'
);
}
if
(
this
.
synchronizingResources
.
length
)
{
throw
new
Error
(
'
Cannot
merge
while synchronizing resources
'
);
throw
new
Error
(
'
Cannot
pull
while synchronizing resources
'
);
}
const
previews
:
[
SyncResource
,
ISyncResourcePreview
][]
=
[];
for
(
const
[
syncResource
,
preview
]
of
this
.
previews
)
{
this
.
synchronizingResources
.
push
([
syncResource
,
preview
.
resourcePreviews
.
map
(
r
=>
r
.
localResource
)]);
this
.
_onSynchronizeResources
.
fire
(
this
.
synchronizingResources
);
const
synchroniser
=
this
.
synchronisers
.
find
(
s
=>
s
.
resource
===
syncResource
)
!
;
let
syncResourcePreview
=
null
;
for
(
const
resourcePreview
of
preview
.
resourcePreviews
)
{
syncResourcePreview
=
await
synchroniser
.
merge
(
resourcePreview
.
remoteResource
,
false
,
this
.
syncHeaders
);
}
if
(
syncResourcePreview
)
{
previews
.
push
([
syncResource
,
syncResourcePreview
]);
const
newPreview
=
await
synchroniser
.
apply
(
false
,
this
.
syncHeaders
);
if
(
newPreview
)
{
previews
.
push
(
this
.
toSyncResourcePreview
(
synchroniser
.
resource
,
newPreview
));
}
this
.
synchronizingResources
.
splice
(
this
.
synchronizingResources
.
findIndex
(
s
=>
s
[
0
]
===
syncResource
),
1
);
this
.
_onSynchronizeResources
.
fire
(
this
.
synchronizingResources
);
...
...
@@ -554,8 +548,9 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
const
synchroniser
=
this
.
synchronisers
.
find
(
s
=>
s
.
resource
===
syncResource
)
!
;
for
(
const
resourcePreview
of
preview
.
resourcePreviews
)
{
const
content
=
await
synchroniser
.
resolveContent
(
resourcePreview
.
remoteResource
)
||
''
;
await
synchroniser
.
accept
PreviewContent
(
resourcePreview
.
remoteResource
,
content
,
true
,
this
.
syncHeaders
);
await
synchroniser
.
accept
(
resourcePreview
.
remoteResource
,
content
);
}
await
synchroniser
.
apply
(
true
,
this
.
syncHeaders
);
this
.
synchronizingResources
.
splice
(
this
.
synchronizingResources
.
findIndex
(
s
=>
s
[
0
]
===
syncResource
),
1
);
this
.
_onSynchronizeResources
.
fire
(
this
.
synchronizingResources
);
}
...
...
@@ -575,8 +570,9 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
const
synchroniser
=
this
.
synchronisers
.
find
(
s
=>
s
.
resource
===
syncResource
)
!
;
for
(
const
resourcePreview
of
preview
.
resourcePreviews
)
{
const
content
=
await
synchroniser
.
resolveContent
(
resourcePreview
.
localResource
)
||
''
;
await
synchroniser
.
accept
PreviewContent
(
resourcePreview
.
localResource
,
content
,
true
,
this
.
syncHeaders
);
await
synchroniser
.
accept
(
resourcePreview
.
localResource
,
content
);
}
await
synchroniser
.
apply
(
true
,
this
.
syncHeaders
);
this
.
synchronizingResources
.
splice
(
this
.
synchronizingResources
.
findIndex
(
s
=>
s
[
0
]
===
syncResource
),
1
);
this
.
_onSynchronizeResources
.
fire
(
this
.
synchronizingResources
);
}
...
...
@@ -643,6 +639,6 @@ function toStrictResourcePreview(resourcePreview: IResourcePreview): IResourcePr
remoteResource
:
resourcePreview
.
remoteResource
,
localChange
:
resourcePreview
.
localChange
,
remoteChange
:
resourcePreview
.
remoteChange
,
merge
d
:
resourcePreview
.
merged
,
merge
State
:
resourcePreview
.
mergeState
,
};
}
src/vs/platform/userDataSync/test/common/snippetsSync.test.ts
浏览文件 @
9e457a6c
...
...
@@ -287,7 +287,8 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
const
conflicts
=
testObject
.
conflicts
;
await
testObject
.
acceptPreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet1
,
false
);
await
testObject
.
accept
(
conflicts
[
0
].
previewResource
,
htmlSnippet1
);
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -327,7 +328,7 @@ suite('SnippetsSync', () => {
await
testObject
.
sync
(
await
testClient
.
manifest
());
let
conflicts
=
testObject
.
conflicts
;
await
testObject
.
accept
PreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
,
false
);
await
testObject
.
accept
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
conflicts
=
testObject
.
conflicts
;
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
...
...
@@ -346,8 +347,9 @@ suite('SnippetsSync', () => {
await
testObject
.
sync
(
await
testClient
.
manifest
());
const
conflicts
=
testObject
.
conflicts
;
await
testObject
.
acceptPreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
,
false
);
await
testObject
.
acceptPreviewContent
(
conflicts
[
1
].
previewResource
,
tsSnippet1
,
false
);
await
testObject
.
accept
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
await
testObject
.
accept
(
conflicts
[
1
].
previewResource
,
tsSnippet1
);
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -461,7 +463,8 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet3
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
await
testObject
.
acceptPreviewContent
(
testObject
.
conflicts
[
0
].
previewResource
,
htmlSnippet2
,
false
);
await
testObject
.
accept
(
testObject
.
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -565,7 +568,8 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
await
testObject
.
acceptPreviewContent
(
testObject
.
conflicts
[
0
].
previewResource
,
htmlSnippet3
,
false
);
await
testObject
.
accept
(
testObject
.
conflicts
[
0
].
previewResource
,
htmlSnippet3
);
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -592,7 +596,8 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
await
testObject
.
acceptPreviewContent
(
testObject
.
conflicts
[
0
].
previewResource
,
''
,
false
);
await
testObject
.
accept
(
testObject
.
conflicts
[
0
].
previewResource
,
''
);
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -689,7 +694,8 @@ suite('SnippetsSync', () => {
await
testObject
.
sync
(
await
testClient
.
manifest
());
let
conflicts
=
testObject
.
conflicts
;
await
testObject
.
acceptPreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
,
false
);
await
testObject
.
accept
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
await
testObject
.
apply
(
false
);
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
assert
.
ok
(
!
await
fileService
.
exists
(
dirname
(
conflicts
[
0
].
previewResource
)));
...
...
@@ -710,7 +716,7 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
...
...
@@ -736,8 +742,36 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
1
].
localResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
1
].
localResource
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
),
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
),
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
});
test
(
'
merge when there are multiple snippets and all snippets are merged and applied
'
,
async
()
=>
{
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
updateSnippet
(
'
typescript.json
'
,
tsSnippet2
,
testClient
);
let
preview
=
await
testObject
.
preview
(
await
testClient
.
manifest
());
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
),
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
),
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
1
].
localResource
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
...
...
@@ -762,7 +796,37 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
),
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
),
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
});
test
(
'
merge when there are multiple snippets and one snippet has no changes and one snippet is merged and applied
'
,
async
()
=>
{
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
await
updateSnippet
(
'
html.json
'
,
htmlSnippet1
,
client2
);
await
client2
.
sync
();
await
updateSnippet
(
'
html.json
'
,
htmlSnippet1
,
testClient
);
await
updateSnippet
(
'
typescript.json
'
,
tsSnippet2
,
testClient
);
let
preview
=
await
testObject
.
preview
(
await
testClient
.
manifest
());
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
),
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
),
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
localResource
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
...
...
@@ -788,7 +852,7 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
assertPreviews
(
preview
!
.
resourcePreviews
,
...
...
@@ -821,8 +885,8 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
1
].
previewResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
1
].
previewResource
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
assertPreviews
(
preview
!
.
resourcePreviews
,
...
...
@@ -856,7 +920,7 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
accept
PreviewContent
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
htmlSnippet2
,
false
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
htmlSnippet2
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
...
...
@@ -886,8 +950,40 @@ suite('SnippetsSync', () => {
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
acceptPreviewContent
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
htmlSnippet2
,
false
);
preview
=
await
testObject
.
acceptPreviewContent
(
preview
!
.
resourcePreviews
[
1
].
previewResource
,
tsSnippet2
,
false
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
htmlSnippet2
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
1
].
previewResource
,
tsSnippet2
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
),
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
),
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
});
test
(
'
accept when there are multiple snippets with conflicts and all snippets are accepted and applied
'
,
async
()
=>
{
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
await
updateSnippet
(
'
html.json
'
,
htmlSnippet1
,
client2
);
await
updateSnippet
(
'
typescript.json
'
,
tsSnippet1
,
client2
);
await
client2
.
sync
();
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
updateSnippet
(
'
typescript.json
'
,
tsSnippet2
,
testClient
);
let
preview
=
await
testObject
.
preview
(
await
testClient
.
manifest
());
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
),
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
),
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
htmlSnippet2
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
1
].
previewResource
,
tsSnippet2
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
...
...
src/vs/platform/userDataSync/test/common/synchronizer.test.ts
浏览文件 @
9e457a6c
...
...
@@ -276,26 +276,54 @@ suite('TestSynchronizer', () => {
assertConflicts
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is s
et to idle
after merging if there are no conflicts
'
,
async
()
=>
{
test
(
'
preview: status is s
yncing
after merging if there are no conflicts
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
false
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
false
);
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
resource
]);
assertConflicts
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is set to idle after merging and applying if there are no conflicts
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
false
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
preview
=
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
assertConflicts
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is syncing after accepting when there are no conflicts
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
false
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
resource
]);
assertConflicts
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is set to idle and sync is applied after accepting when there are no conflicts before merging
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
false
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
preview
=
await
testObject
.
acceptPreviewContent
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
,
false
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
...
...
@@ -320,34 +348,63 @@ suite('TestSynchronizer', () => {
testObject
.
syncBarrier
.
open
();
const
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
false
);
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
resource
]);
assertConflicts
(
testObject
.
conflicts
,
[
preview
!
.
resourcePreviews
[
0
].
previewResource
]);
});
test
(
'
preview: status is syncing after accepting when there are conflicts
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
true
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
resource
]);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is set to idle and sync is applied after accepting when there are conflicts
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
true
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
false
);
preview
=
await
testObject
.
acceptPreviewContent
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
,
false
);
await
testObject
.
merge
(
preview
!
.
resourcePreviews
[
0
].
previewResource
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
assertConflicts
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is set to syncing after accepting when there are conflicts before merging
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
true
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Syncing
);
assertPreviews
(
preview
!
.
resourcePreviews
,
[
resource
]);
assertConflicts
(
testObject
.
conflicts
,
[]);
});
test
(
'
preview: status is set to idle and sync is applied after accepting when there are conflicts before merging
'
,
async
()
=>
{
const
testObject
:
TestSynchroniser
=
client
.
instantiationService
.
createInstance
(
TestSynchroniser
,
SyncResource
.
Settings
);
testObject
.
syncResult
=
{
hasConflicts
:
true
,
hasError
:
false
};
testObject
.
syncBarrier
.
open
();
let
preview
=
await
testObject
.
preview
(
await
client
.
manifest
());
preview
=
await
testObject
.
acceptPreviewContent
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
,
false
);
preview
=
await
testObject
.
accept
(
preview
!
.
resourcePreviews
[
0
].
previewResource
,
preview
!
.
resourcePreviews
[
0
].
previewContent
!
);
preview
=
await
testObject
.
apply
(
false
);
assert
.
deepEqual
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
equal
(
preview
,
null
);
...
...
src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts
浏览文件 @
9e457a6c
...
...
@@ -240,7 +240,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
for
(
const
conflict
of
conflicts
)
{
const
modelRef
=
await
this
.
textModelResolverService
.
createModelReference
(
conflict
.
remoteResource
);
try
{
await
this
.
userDataSyncService
.
accept
PreviewContent
(
syncResource
,
conflict
.
remoteResource
,
modelRef
.
object
.
textEditorModel
.
getValue
()
);
await
this
.
userDataSyncService
.
accept
(
syncResource
,
conflict
.
remoteResource
,
modelRef
.
object
.
textEditorModel
.
getValue
(),
true
);
}
finally
{
modelRef
.
dispose
();
}
...
...
@@ -255,7 +255,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
for
(
const
conflict
of
conflicts
)
{
const
modelRef
=
await
this
.
textModelResolverService
.
createModelReference
(
conflict
.
previewResource
);
try
{
await
this
.
userDataSyncService
.
accept
PreviewContent
(
syncResource
,
conflict
.
previewResource
,
modelRef
.
object
.
textEditorModel
.
getValue
()
);
await
this
.
userDataSyncService
.
accept
(
syncResource
,
conflict
.
previewResource
,
modelRef
.
object
.
textEditorModel
.
getValue
(),
true
);
}
finally
{
modelRef
.
dispose
();
}
...
...
@@ -1195,7 +1195,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
});
if
(
result
.
confirmed
)
{
try
{
await
this
.
userDataSyncService
.
accept
PreviewContent
(
syncResource
,
model
.
uri
,
model
.
getValue
()
);
await
this
.
userDataSyncService
.
accept
(
syncResource
,
model
.
uri
,
model
.
getValue
(),
true
);
}
catch
(
e
)
{
if
(
e
instanceof
UserDataSyncError
&&
e
.
code
===
UserDataSyncErrorCode
.
LocalPreconditionFailed
)
{
const
syncResourceCoflicts
=
this
.
userDataSyncService
.
conflicts
.
filter
(
syncResourceCoflicts
=>
syncResourceCoflicts
[
0
]
===
syncResource
)[
0
];
...
...
src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts
浏览文件 @
9e457a6c
...
...
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IUserDataSyncService
,
IAuthenticationProvider
,
getUserDataSyncStore
,
isAuthenticationProvider
,
IUserDataAutoSyncService
,
SyncResource
,
IResourcePreview
,
ISyncResourcePreview
,
Change
,
IManualSyncTask
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IUserDataSyncService
,
IAuthenticationProvider
,
getUserDataSyncStore
,
isAuthenticationProvider
,
IUserDataAutoSyncService
,
SyncResource
,
IResourcePreview
,
ISyncResourcePreview
,
Change
,
IManualSyncTask
,
MergeState
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
registerSingleton
}
from
'
vs/platform/instantiation/common/extensions
'
;
import
{
IUserDataSyncWorkbenchService
,
IUserDataSyncAccount
,
AccountStatus
,
CONTEXT_SYNC_ENABLEMENT
,
CONTEXT_SYNC_STATE
,
CONTEXT_ACCOUNT_STATE
,
SHOW_SYNC_LOG_COMMAND_ID
,
getSyncAreaLabel
,
IUserDataSyncPreview
,
IUserDataSyncResourceGroup
,
CONTEXT_ENABLE_MANUAL_SYNC_VIEW
,
MANUAL_SYNC_VIEW_ID
,
CONTEXT_ENABLE_ACTIVITY_VIEWS
,
SYNC_VIEW_CONTAINER_ID
}
from
'
vs/workbench/services/userDataSync/common/userDataSync
'
;
...
...
@@ -270,7 +270,7 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
synchronizingResources
.
length
?
progress
.
report
({
message
:
localize
(
'
syncing resource
'
,
"
Syncing {0}...
"
,
getSyncAreaLabel
(
synchronizingResources
[
0
][
0
]))
})
:
undefined
);
try
{
switch
(
action
)
{
case
'
merge
'
:
return
await
manualSyncTask
.
merge
();
case
'
merge
'
:
return
await
manualSyncTask
.
apply
();
case
'
pull
'
:
return
await
manualSyncTask
.
pull
();
case
'
push
'
:
return
await
manualSyncTask
.
push
();
case
'
manual
'
:
return
;
...
...
@@ -343,7 +343,7 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
}
/* Merge to sync globalState changes */
await
task
.
merge
();
await
task
.
apply
();
this
.
userDataSyncPreview
.
unsetManualSyncPreview
();
...
...
@@ -599,11 +599,11 @@ class UserDataSyncPreview extends Disposable implements IUserDataSyncPreview {
const
syncPreview
=
await
this
.
manualSync
.
task
.
accept
(
resource
,
content
);
this
.
updatePreview
(
syncPreview
);
}
else
{
await
this
.
userDataSyncService
.
accept
PreviewContent
(
syncResource
,
resource
,
content
);
await
this
.
userDataSyncService
.
accept
(
syncResource
,
resource
,
content
,
false
);
}
}
async
merge
(
resource
?
:
URI
):
Promise
<
void
>
{
async
merge
(
resource
:
URI
):
Promise
<
void
>
{
if
(
!
this
.
manualSync
)
{
throw
new
Error
(
'
Can merge only while syncing manually
'
);
}
...
...
@@ -650,10 +650,9 @@ class UserDataSyncPreview extends Disposable implements IUserDataSyncPreview {
.
map
(([
syncResource
,
syncResourcePreview
])
=>
([
syncResource
,
/* remove
merged previews and conflicts and with no change
s and conflicts */
/* remove
accepted preview
s and conflicts */
syncResourcePreview
.
resourcePreviews
.
filter
(
r
=>
!
r
.
merged
&&
(
r
.
localChange
!==
Change
.
None
||
r
.
remoteChange
!==
Change
.
None
)
r
.
mergeState
!==
MergeState
.
Accepted
&&
!
this
.
_conflicts
.
some
(
c
=>
c
.
syncResource
===
syncResource
&&
isEqual
(
c
.
local
,
r
.
localResource
)))
]))
);
...
...
src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts
浏览文件 @
9e457a6c
...
...
@@ -102,8 +102,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return
this
.
channel
.
call
(
'
hasLocalData
'
);
}
accept
PreviewContent
(
syncResource
:
SyncResource
,
resource
:
URI
,
content
:
string
):
Promise
<
void
>
{
return
this
.
channel
.
call
(
'
accept
PreviewContent
'
,
[
syncResource
,
resource
,
content
]);
accept
(
syncResource
:
SyncResource
,
resource
:
URI
,
content
:
string
,
apply
:
boolean
):
Promise
<
void
>
{
return
this
.
channel
.
call
(
'
accept
'
,
[
syncResource
,
resource
,
content
,
apply
]);
}
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
{
...
...
@@ -191,11 +191,16 @@ class ManualSyncTask implements IManualSyncTask {
return
this
.
deserializePreviews
(
previews
);
}
async
merge
(
resource
?
:
URI
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
async
merge
(
resource
:
URI
):
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
const
previews
=
await
this
.
channel
.
call
<
[
SyncResource
,
ISyncResourcePreview
][]
>
(
'
merge
'
,
[
resource
]);
return
this
.
deserializePreviews
(
previews
);
}
async
apply
():
Promise
<
[
SyncResource
,
ISyncResourcePreview
][]
>
{
const
previews
=
await
this
.
channel
.
call
<
[
SyncResource
,
ISyncResourcePreview
][]
>
(
'
apply
'
);
return
this
.
deserializePreviews
(
previews
);
}
pull
():
Promise
<
void
>
{
return
this
.
channel
.
call
(
'
pull
'
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录