Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
793c1b28
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,发现更多精彩内容 >>
提交
793c1b28
编写于
7月 09, 2020
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
#100346 Use resource previews and remove conflict type
上级
80257234
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
151 addition
and
129 deletion
+151
-129
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
+62
-66
src/vs/platform/userDataSync/common/settingsSync.ts
src/vs/platform/userDataSync/common/settingsSync.ts
+1
-2
src/vs/platform/userDataSync/common/userDataSync.ts
src/vs/platform/userDataSync/common/userDataSync.ts
+6
-7
src/vs/platform/userDataSync/common/userDataSyncIpc.ts
src/vs/platform/userDataSync/common/userDataSyncIpc.ts
+1
-1
src/vs/platform/userDataSync/common/userDataSyncService.ts
src/vs/platform/userDataSync/common/userDataSyncService.ts
+19
-8
src/vs/platform/userDataSync/test/common/snippetsSync.test.ts
...vs/platform/userDataSync/test/common/snippetsSync.test.ts
+35
-23
src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts
...vs/workbench/contrib/userDataSync/browser/userDataSync.ts
+18
-18
src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts
...ices/userDataSync/electron-browser/userDataSyncService.ts
+9
-4
未找到文件。
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
浏览文件 @
793c1b28
...
...
@@ -9,7 +9,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
SyncResource
,
SyncStatus
,
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
UserDataSyncError
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
IUserDataSyncResourceEnablementService
,
IUserDataSyncBackupStoreService
,
Conflict
,
ISyncResourceHandle
,
USER_DATA_SYNC_SCHEME
,
ISyncResourcePreview
as
IBaseSyncResourcePreview
,
IUserDataSyncResourceEnablementService
,
IUserDataSyncBackupStoreService
,
ISyncResourceHandle
,
USER_DATA_SYNC_SCHEME
,
ISyncResourcePreview
as
IBaseSyncResourcePreview
,
IUserDataManifest
,
ISyncData
,
IRemoteUserData
,
PREVIEW_DIR_NAME
,
IResourcePreview
as
IBaseResourcePreview
,
Change
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
...
...
@@ -78,10 +78,11 @@ export abstract class AbstractSynchroniser extends Disposable {
private
_onDidChangStatus
:
Emitter
<
SyncStatus
>
=
this
.
_register
(
new
Emitter
<
SyncStatus
>
());
readonly
onDidChangeStatus
:
Event
<
SyncStatus
>
=
this
.
_onDidChangStatus
.
event
;
private
_conflicts
:
Conflict
[]
=
[];
get
conflicts
():
Conflict
[]
{
return
this
.
_conflicts
;
}
private
_onDidChangeConflicts
:
Emitter
<
Conflict
[]
>
=
this
.
_register
(
new
Emitter
<
Conflict
[]
>
());
readonly
onDidChangeConflicts
:
Event
<
Conflict
[]
>
=
this
.
_onDidChangeConflicts
.
event
;
private
_resourcePreviews
:
IResourcePreview
[]
=
[];
get
resourcePreviews
():
IResourcePreview
[]
{
return
this
.
_resourcePreviews
;
}
get
conflicts
():
IResourcePreview
[]
{
return
this
.
_resourcePreviews
.
filter
(({
hasConflicts
})
=>
hasConflicts
);
}
private
_onDidChangeConflicts
:
Emitter
<
IResourcePreview
[]
>
=
this
.
_register
(
new
Emitter
<
IResourcePreview
[]
>
());
readonly
onDidChangeConflicts
:
Event
<
IResourcePreview
[]
>
=
this
.
_onDidChangeConflicts
.
event
;
private
readonly
localChangeTriggerScheduler
=
new
RunOnceScheduler
(()
=>
this
.
doTriggerLocalChange
(),
50
);
private
readonly
_onDidChangeLocal
:
Emitter
<
void
>
=
this
.
_register
(
new
Emitter
<
void
>
());
...
...
@@ -155,16 +156,6 @@ export abstract class AbstractSynchroniser extends Disposable {
// Log to telemetry when conflicts are resolved
this
.
telemetryService
.
publicLog2
<
{
source
:
string
},
SyncSourceClassification
>
(
'
sync/conflictsResolved
'
,
{
source
:
this
.
resource
});
}
if
(
this
.
status
!==
SyncStatus
.
HasConflicts
)
{
this
.
setConflicts
([]);
}
}
}
private
setConflicts
(
conflicts
:
Conflict
[])
{
if
(
!
equals
(
this
.
_conflicts
,
conflicts
,
(
a
,
b
)
=>
isEqual
(
a
.
local
,
b
.
local
)
&&
isEqual
(
a
.
remote
,
b
.
remote
)))
{
this
.
_conflicts
=
conflicts
;
this
.
_onDidChangeConflicts
.
fire
(
this
.
_conflicts
);
}
}
...
...
@@ -364,6 +355,9 @@ export abstract class AbstractSynchroniser extends Disposable {
// reset preview
this
.
syncPreviewPromise
=
null
;
// reset resource previews
await
this
.
updateResourcePreviews
([],
CancellationToken
.
None
);
return
SyncStatus
.
Idle
;
}
catch
(
error
)
{
...
...
@@ -374,47 +368,50 @@ export abstract class AbstractSynchroniser extends Disposable {
}
}
async
acceptConflict
(
conflictUri
:
URI
,
conflictContent
:
string
):
Promise
<
void
>
{
let
preview
=
this
.
syncPreviewPromise
?
await
this
.
syncPreviewPromise
:
null
;
if
(
!
preview
||
!
preview
.
resourcePreviews
.
some
(({
hasConflicts
})
=>
hasConflicts
))
{
async
acceptPreviewContent
(
resource
:
URI
,
content
:
string
):
Promise
<
void
>
{
if
(
!
this
.
syncPreviewPromise
)
{
return
;
}
let
preview
=
await
this
.
syncPreviewPromise
;
this
.
syncPreviewPromise
=
createCancelablePromise
(
async
token
=>
{
const
newPreview
=
await
this
.
updateSyncResourcePreviewWithConflict
(
preview
!
,
conflictUri
,
conflictContent
,
token
);
await
this
.
updateConflicts
(
newPreview
.
resourcePreviews
,
token
);
const
newPreview
=
await
this
.
updateSyncResourcePreviewContent
(
preview
,
resource
,
content
,
token
);
if
(
!
token
.
isCancellationRequested
)
{
await
this
.
updateResourcePreviews
(
newPreview
.
resourcePreviews
,
token
);
}
return
newPreview
;
});
preview
=
await
this
.
syncPreviewPromise
;
if
(
!
preview
.
resourcePreviews
.
some
(({
hasConflicts
})
=>
hasConflicts
))
{
//
apply preview
//
Apply preview if there are no conflicts
await
this
.
applyPreview
(
preview
.
remoteUserData
,
preview
.
lastSyncUserData
,
preview
.
resourcePreviews
,
false
);
// reset preview
this
.
syncPreviewPromise
=
null
;
// reset resource previews
await
this
.
updateResourcePreviews
([],
CancellationToken
.
None
);
// reset status
this
.
setStatus
(
SyncStatus
.
Idle
);
}
}
private
async
updateSyncResourcePreviewWithConflict
(
preview
:
ISyncResourcePreview
,
conflictResource
:
URI
,
previewContent
:
string
,
token
:
CancellationToken
):
Promise
<
ISyncResourcePreview
>
{
const
conflict
=
this
.
conflicts
.
find
(({
local
,
remote
})
=>
isEqual
(
local
,
conflictResource
)
||
isEqual
(
remote
,
conflictResource
));
if
(
!
conflict
)
{
return
preview
;
}
const
index
=
preview
.
resourcePreviews
.
findIndex
(({
previewResource
})
=>
previewResource
&&
isEqual
(
previewResource
,
conflict
.
local
));
if
(
index
===
-
1
)
{
return
preview
;
private
async
updateSyncResourcePreviewContent
(
preview
:
ISyncResourcePreview
,
resource
:
URI
,
previewContent
:
string
,
token
:
CancellationToken
):
Promise
<
ISyncResourcePreview
>
{
const
index
=
preview
.
resourcePreviews
.
findIndex
(({
localResource
,
remoteResource
,
previewResource
})
=>
isEqual
(
localResource
,
resource
)
||
isEqual
(
remoteResource
,
resource
)
||
isEqual
(
previewResource
,
resource
));
if
(
index
!==
-
1
)
{
const
resourcePreviews
=
[...
preview
.
resourcePreviews
];
const
resourcePreview
=
await
this
.
updateResourcePreviewContent
(
resourcePreviews
[
index
],
resource
,
previewContent
,
token
);
resourcePreviews
[
index
]
=
resourcePreview
;
preview
=
{
...
preview
,
resourcePreviews
};
}
const
resourcePreviews
=
[...
preview
.
resourcePreviews
];
const
resourcePreview
=
await
this
.
updateResourcePreviewContent
(
resourcePreviews
[
index
],
conflictResource
,
previewContent
,
token
);
resourcePreviews
[
index
]
=
resourcePreview
;
return
{
...
preview
,
resourcePreviews
};
return
preview
;
}
protected
async
updateResourcePreviewContent
(
resourcePreview
:
IResourcePreview
,
resource
:
URI
,
previewContent
:
string
,
token
:
CancellationToken
):
Promise
<
IResourcePreview
>
{
...
...
@@ -427,27 +424,25 @@ export abstract class AbstractSynchroniser extends Disposable {
};
}
private
async
updateConflicts
(
resourcePreviews
:
IResourcePreview
[],
token
:
CancellationToken
):
Promise
<
void
>
{
const
conflicts
:
Conflict
[]
=
[];
for
(
const
resourcePreview
of
resourcePreviews
)
{
if
(
resourcePreview
.
hasConflicts
)
{
conflicts
.
push
({
local
:
resourcePreview
.
previewResource
!
,
remote
:
resourcePreview
.
remoteResource
!
});
}
}
private
async
updateResourcePreviews
(
resourcePreviews
:
IResourcePreview
[],
token
:
CancellationToken
):
Promise
<
void
>
{
const
oldConflicts
=
this
.
conflicts
;
const
oldPreviews
=
this
.
_resourcePreviews
;
this
.
_resourcePreviews
=
resourcePreviews
;
for
(
const
conflict
of
this
.
conflicts
)
{
// clear obsolete conflicts
if
(
!
conflicts
.
some
(({
local
})
=>
isEqual
(
local
,
conflict
.
local
)))
{
// clear obsolete previews
for
(
const
resourcePreview
of
oldPreviews
)
{
if
(
!
this
.
_resourcePreviews
.
some
(({
previewResource
})
=>
isEqual
(
previewResource
,
resourcePreview
.
previewResource
)))
{
try
{
await
this
.
fileService
.
del
(
conflict
.
local
);
}
catch
(
error
)
{
// Ignore & log
this
.
logService
.
error
(
error
);
}
await
this
.
fileService
.
del
(
resourcePreview
.
previewResource
);
}
catch
(
error
)
{
/* Ignore */
}
}
}
this
.
setConflicts
(
conflicts
);
// update conflicts
const
newConflicts
=
this
.
conflicts
;
if
(
!
equals
(
oldConflicts
,
newConflicts
,
(
a
,
b
)
=>
isEqual
(
a
.
previewResource
,
b
.
previewResource
)))
{
this
.
_onDidChangeConflicts
.
fire
(
newConflicts
);
}
}
async
hasPreviouslySynced
():
Promise
<
boolean
>
{
...
...
@@ -528,7 +523,11 @@ export abstract class AbstractSynchroniser extends Disposable {
// For preview, use remoteUserData if lastSyncUserData does not exists and last sync is from current machine
const
lastSyncUserDataForPreview
=
lastSyncUserData
===
null
&&
isLastSyncFromCurrentMachine
?
remoteUserData
:
lastSyncUserData
;
const
resourcePreviews
=
await
this
.
generateSyncPreview
(
remoteUserData
,
lastSyncUserDataForPreview
,
token
);
await
this
.
updateConflicts
(
resourcePreviews
,
token
);
if
(
!
token
.
isCancellationRequested
)
{
await
this
.
updateResourcePreviews
(
resourcePreviews
,
token
);
}
return
{
remoteUserData
,
lastSyncUserData
,
resourcePreviews
,
isLastSyncFromCurrentMachine
};
}
...
...
@@ -605,23 +604,20 @@ export abstract class AbstractSynchroniser extends Disposable {
}
async
stop
():
Promise
<
void
>
{
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: Stopped synchronizing
${
this
.
resource
.
toLowerCase
()}
.`
);
if
(
this
.
status
===
SyncStatus
.
Idle
)
{
return
;
}
this
.
logService
.
trace
(
`
${
this
.
syncResourceLogLabel
}
: Stopping synchronizing
${
this
.
resource
.
toLowerCase
()}
.`
);
if
(
this
.
syncPreviewPromise
)
{
this
.
syncPreviewPromise
.
cancel
();
this
.
syncPreviewPromise
=
null
;
}
if
(
this
.
conflicts
.
length
)
{
await
Promise
.
all
(
this
.
conflicts
.
map
(
async
({
local
})
=>
{
try
{
this
.
fileService
.
del
(
local
);
}
catch
(
error
)
{
// Ignore & log
this
.
logService
.
error
(
error
);
}
}));
this
.
setConflicts
([]);
}
await
this
.
updateResourcePreviews
([],
CancellationToken
.
None
);
this
.
setStatus
(
SyncStatus
.
Idle
);
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: Stopped synchronizing
${
this
.
resource
.
toLowerCase
()}
.`
);
}
protected
abstract
readonly
version
:
number
;
...
...
src/vs/platform/userDataSync/common/settingsSync.ts
浏览文件 @
793c1b28
...
...
@@ -144,6 +144,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
const
formattingOptions
=
await
this
.
getFormattingOptions
();
const
remoteSettingsSyncContent
=
this
.
getSettingsSyncContent
(
remoteUserData
);
const
lastSettingsSyncContent
:
ISettingsSyncContent
|
null
=
lastSyncUserData
?
this
.
getSettingsSyncContent
(
lastSyncUserData
)
:
null
;
const
ignoredSettings
=
await
this
.
getIgnoredSettings
();
let
previewContent
:
string
|
null
=
null
;
let
hasLocalChanged
:
boolean
=
false
;
...
...
@@ -154,7 +155,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
const
localContent
:
string
=
fileContent
?
fileContent
.
value
.
toString
()
:
'
{}
'
;
this
.
validateContent
(
localContent
);
this
.
logService
.
trace
(
`
${
this
.
syncResourceLogLabel
}
: Merging remote settings with local settings...`
);
const
ignoredSettings
=
await
this
.
getIgnoredSettings
();
const
result
=
merge
(
localContent
,
remoteSettingsSyncContent
.
settings
,
lastSettingsSyncContent
?
lastSettingsSyncContent
.
settings
:
null
,
ignoredSettings
,
[],
formattingOptions
);
previewContent
=
result
.
localContent
||
result
.
remoteContent
;
hasLocalChanged
=
result
.
localContent
!==
null
;
...
...
@@ -171,7 +171,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
if
(
previewContent
&&
!
token
.
isCancellationRequested
)
{
// Remove the ignored settings from the preview.
const
ignoredSettings
=
await
this
.
getIgnoredSettings
();
const
content
=
updateIgnoredSettings
(
previewContent
,
'
{}
'
,
ignoredSettings
,
formattingOptions
);
await
this
.
fileService
.
writeFile
(
this
.
localPreviewResource
,
VSBuffer
.
fromString
(
content
));
}
...
...
src/vs/platform/userDataSync/common/userDataSync.ts
浏览文件 @
793c1b28
...
...
@@ -281,8 +281,6 @@ export interface ISyncResourceHandle {
uri
:
URI
;
}
export
type
Conflict
=
{
remote
:
URI
,
local
:
URI
};
export
interface
IRemoteUserData
{
ref
:
string
;
syncData
:
ISyncData
|
null
;
...
...
@@ -320,8 +318,9 @@ export interface IUserDataSynchroniser {
readonly
resource
:
SyncResource
;
readonly
status
:
SyncStatus
;
readonly
onDidChangeStatus
:
Event
<
SyncStatus
>
;
readonly
conflicts
:
Conflict
[];
readonly
onDidChangeConflicts
:
Event
<
Conflict
[]
>
;
readonly
resourcePreviews
:
IResourcePreview
[];
readonly
conflicts
:
IResourcePreview
[];
readonly
onDidChangeConflicts
:
Event
<
IResourcePreview
[]
>
;
readonly
onDidChangeLocal
:
Event
<
void
>
;
pull
():
Promise
<
void
>
;
...
...
@@ -336,7 +335,7 @@ export interface IUserDataSynchroniser {
resetLocal
():
Promise
<
void
>
;
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
;
accept
Conflict
(
conflictR
esource
:
URI
,
content
:
string
):
Promise
<
void
>
;
accept
PreviewContent
(
r
esource
:
URI
,
content
:
string
):
Promise
<
void
>
;
getRemoteSyncResourceHandles
():
Promise
<
ISyncResourceHandle
[]
>
;
getLocalSyncResourceHandles
():
Promise
<
ISyncResourceHandle
[]
>
;
...
...
@@ -357,7 +356,7 @@ export interface IUserDataSyncResourceEnablementService {
setResourceEnablement
(
resource
:
SyncResource
,
enabled
:
boolean
):
void
;
}
export
type
SyncResourceConflicts
=
{
syncResource
:
SyncResource
,
conflicts
:
Conflict
[]
};
export
type
SyncResourceConflicts
=
{
syncResource
:
SyncResource
,
conflicts
:
IResourcePreview
[]
};
export
interface
ISyncTask
{
manifest
:
IUserDataManifest
|
null
;
...
...
@@ -393,7 +392,7 @@ export interface IUserDataSyncService {
isFirstTimeSyncingWithAnotherMachine
():
Promise
<
boolean
>
;
hasPreviouslySynced
():
Promise
<
boolean
>
;
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
;
accept
Conflic
t
(
conflictResource
:
URI
,
content
:
string
):
Promise
<
void
>
;
accept
PreviewConten
t
(
conflictResource
:
URI
,
content
:
string
):
Promise
<
void
>
;
getLocalSyncResourceHandles
(
resource
:
SyncResource
):
Promise
<
ISyncResourceHandle
[]
>
;
getRemoteSyncResourceHandles
(
resource
:
SyncResource
):
Promise
<
ISyncResourceHandle
[]
>
;
...
...
src/vs/platform/userDataSync/common/userDataSyncIpc.ts
浏览文件 @
793c1b28
...
...
@@ -52,7 +52,7 @@ export class UserDataSyncChannel implements IServerChannel {
case
'
resetLocal
'
:
return
this
.
service
.
resetLocal
();
case
'
hasPreviouslySynced
'
:
return
this
.
service
.
hasPreviouslySynced
();
case
'
isFirstTimeSyncingWithAnotherMachine
'
:
return
this
.
service
.
isFirstTimeSyncingWithAnotherMachine
();
case
'
accept
Conflict
'
:
return
this
.
service
.
acceptConflic
t
(
URI
.
revive
(
args
[
0
]),
args
[
1
]);
case
'
accept
PreviewContent
'
:
return
this
.
service
.
acceptPreviewConten
t
(
URI
.
revive
(
args
[
0
]),
args
[
1
]);
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
]);
...
...
src/vs/platform/userDataSync/common/userDataSyncService.ts
浏览文件 @
793c1b28
...
...
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IUserDataSyncService
,
SyncStatus
,
IUserDataSyncStoreService
,
SyncResource
,
IUserDataSyncLogService
,
IUserDataSynchroniser
,
UserDataSyncErrorCode
,
UserDataSyncError
,
SyncResourceConflicts
,
ISyncResourceHandle
,
IUserDataManifest
,
ISyncTask
,
Change
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IUserDataSyncService
,
SyncStatus
,
IUserDataSyncStoreService
,
SyncResource
,
IUserDataSyncLogService
,
IUserDataSynchroniser
,
UserDataSyncErrorCode
,
UserDataSyncError
,
SyncResourceConflicts
,
ISyncResourceHandle
,
IUserDataManifest
,
ISyncTask
,
Change
,
IResourcePreview
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
...
...
@@ -239,12 +239,12 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
}
async
accept
Conflict
(
conflict
:
URI
,
content
:
string
):
Promise
<
void
>
{
async
accept
PreviewContent
(
resource
:
URI
,
content
:
string
):
Promise
<
void
>
{
await
this
.
checkEnablement
();
const
sync
ResourceConflict
=
this
.
conflicts
.
filter
(({
conflicts
})
=>
conflicts
.
some
(({
local
,
remote
})
=>
isEqual
(
conflict
,
local
)
||
isEqual
(
conflict
,
remote
)))[
0
];
if
(
syncResourceConflict
)
{
const
synchroniser
=
this
.
getSynchroniser
(
syncResourceConflict
.
syncResource
);
await
synchroniser
.
accept
Conflict
(
conflict
,
content
);
const
sync
hroniser
=
this
.
synchronisers
.
find
(
synchroniser
=>
synchroniser
.
resourcePreviews
.
some
(({
localResource
,
previewResource
,
remoteResource
})
=>
isEqual
(
resource
,
localResource
)
||
isEqual
(
resource
,
previewResource
)
||
isEqual
(
resource
,
remoteResource
)));
if
(
synchroniser
)
{
await
synchroniser
.
accept
PreviewContent
(
resource
,
content
);
}
}
...
...
@@ -365,7 +365,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
private
updateConflicts
():
void
{
const
conflicts
=
this
.
computeConflicts
();
if
(
!
equals
(
this
.
_conflicts
,
conflicts
,
(
a
,
b
)
=>
a
.
syncResource
===
b
.
syncResource
&&
equals
(
a
.
conflicts
,
b
.
conflicts
,
(
a
,
b
)
=>
isEqual
(
a
.
local
,
b
.
local
)
&&
isEqual
(
a
.
remote
,
b
.
remot
e
))))
{
if
(
!
equals
(
this
.
_conflicts
,
conflicts
,
(
a
,
b
)
=>
a
.
syncResource
===
b
.
syncResource
&&
equals
(
a
.
conflicts
,
b
.
conflicts
,
(
a
,
b
)
=>
isEqual
(
a
.
previewResource
,
b
.
previewResourc
e
))))
{
this
.
_conflicts
=
this
.
computeConflicts
();
this
.
_onDidChangeConflicts
.
fire
(
conflicts
);
}
...
...
@@ -412,7 +412,18 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
private
computeConflicts
():
SyncResourceConflicts
[]
{
return
this
.
synchronisers
.
filter
(
s
=>
s
.
status
===
SyncStatus
.
HasConflicts
)
.
map
(
s
=>
({
syncResource
:
s
.
resource
,
conflicts
:
s
.
conflicts
}));
.
map
(
s
=>
({
syncResource
:
s
.
resource
,
conflicts
:
s
.
conflicts
.
map
(
r
=>
this
.
toStrictResourcePreview
(
r
))
}));
}
private
toStrictResourcePreview
(
resourcePreview
:
IResourcePreview
):
IResourcePreview
{
return
{
localResource
:
resourcePreview
.
localResource
,
previewResource
:
resourcePreview
.
previewResource
,
remoteResource
:
resourcePreview
.
remoteResource
,
localChange
:
resourcePreview
.
localChange
,
remoteChange
:
resourcePreview
.
remoteChange
,
hasConflicts
:
resourcePreview
.
hasConflicts
,
};
}
getSynchroniser
(
source
:
SyncResource
):
IUserDataSynchroniser
{
...
...
src/vs/platform/userDataSync/test/common/snippetsSync.test.ts
浏览文件 @
793c1b28
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
IUserDataSyncStoreService
,
IUserDataSyncService
,
SyncResource
,
SyncStatus
,
Conflict
,
USER_DATA_SYNC_SCHEME
,
PREVIEW_DIR_NAME
,
ISyncData
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IUserDataSyncStoreService
,
IUserDataSyncService
,
SyncResource
,
SyncStatus
,
PREVIEW_DIR_NAME
,
ISyncData
,
IResourcePreview
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
UserDataSyncClient
,
UserDataSyncTestServer
}
from
'
vs/platform/userDataSync/test/common/userDataSyncClient
'
;
import
{
DisposableStore
,
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
UserDataSyncService
}
from
'
vs/platform/userDataSync/common/userDataSyncService
'
;
...
...
@@ -14,6 +14,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import
{
SnippetsSynchroniser
}
from
'
vs/platform/userDataSync/common/snippetsSync
'
;
import
{
joinPath
}
from
'
vs/base/common/resources
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
const
tsSnippet1
=
`{
...
...
@@ -276,7 +277,7 @@ suite('SnippetsSync', () => {
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
const
local
=
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
);
assertConflicts
(
testObject
.
conflicts
,
[
{
local
,
remote
:
local
.
with
({
scheme
:
USER_DATA_SYNC_SCHEME
})
}
]);
assertConflicts
(
testObject
.
conflicts
,
[
local
]);
});
test
(
'
first time sync when snippets exists - has conflicts and accept conflicts
'
,
async
()
=>
{
...
...
@@ -286,12 +287,12 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
const
conflicts
=
testObject
.
conflicts
;
await
testObject
.
accept
Conflict
(
conflicts
[
0
].
local
,
htmlSnippet1
);
await
testObject
.
accept
PreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet1
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
0
].
local
));
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
0
].
previewResource
));
const
actual1
=
await
readSnippet
(
'
html.json
'
,
testClient
);
assert
.
equal
(
actual1
,
htmlSnippet1
);
...
...
@@ -315,10 +316,7 @@ suite('SnippetsSync', () => {
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
const
local1
=
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
);
const
local2
=
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
);
assertConflicts
(
testObject
.
conflicts
,
[
{
local
:
local1
,
remote
:
local1
.
with
({
scheme
:
USER_DATA_SYNC_SCHEME
})
},
{
local
:
local2
,
remote
:
local2
.
with
({
scheme
:
USER_DATA_SYNC_SCHEME
})
}
]);
assertConflicts
(
testObject
.
conflicts
,
[
local1
,
local2
]);
});
test
(
'
first time sync when snippets exists - has multiple conflicts and accept one conflict
'
,
async
()
=>
{
...
...
@@ -331,15 +329,13 @@ suite('SnippetsSync', () => {
await
testObject
.
sync
(
await
testClient
.
manifest
());
let
conflicts
=
testObject
.
conflicts
;
await
testObject
.
acceptConflict
(
conflicts
[
0
].
local
,
htmlSnippet2
);
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
0
].
local
));
await
testObject
.
acceptPreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
conflicts
=
testObject
.
conflicts
;
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
const
local
=
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
typescript.json
'
);
assertConflicts
(
testObject
.
conflicts
,
[
{
local
,
remote
:
local
.
with
({
scheme
:
USER_DATA_SYNC_SCHEME
})
}
]);
assertConflicts
(
testObject
.
conflicts
,
[
local
]);
});
test
(
'
first time sync when snippets exists - has multiple conflicts and accept all conflicts
'
,
async
()
=>
{
...
...
@@ -352,14 +348,14 @@ suite('SnippetsSync', () => {
await
testObject
.
sync
(
await
testClient
.
manifest
());
const
conflicts
=
testObject
.
conflicts
;
await
testObject
.
accept
Conflict
(
conflicts
[
0
].
local
,
htmlSnippet2
);
await
testObject
.
accept
Conflict
(
conflicts
[
1
].
local
,
tsSnippet1
);
await
testObject
.
accept
PreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
await
testObject
.
accept
PreviewContent
(
conflicts
[
1
].
previewResource
,
tsSnippet1
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
0
].
local
));
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
1
].
local
));
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
0
].
previewResource
));
assert
.
ok
(
!
await
fileService
.
exists
(
conflicts
[
1
].
previewResource
));
const
actual1
=
await
readSnippet
(
'
html.json
'
,
testClient
);
assert
.
equal
(
actual1
,
htmlSnippet2
);
...
...
@@ -457,7 +453,7 @@ suite('SnippetsSync', () => {
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
const
local
=
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
);
assertConflicts
(
testObject
.
conflicts
,
[
{
local
,
remote
:
local
.
with
({
scheme
:
USER_DATA_SYNC_SCHEME
})
}
]);
assertConflicts
(
testObject
.
conflicts
,
[
local
]);
});
test
(
'
sync updating a snippet - resolve conflict
'
,
async
()
=>
{
...
...
@@ -470,7 +466,7 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet3
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
await
testObject
.
accept
Conflict
(
testObject
.
conflicts
[
0
].
local
,
htmlSnippet2
);
await
testObject
.
accept
PreviewContent
(
testObject
.
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -560,7 +556,7 @@ suite('SnippetsSync', () => {
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
HasConflicts
);
const
environmentService
=
testClient
.
instantiationService
.
get
(
IEnvironmentService
);
const
local
=
joinPath
(
environmentService
.
userDataSyncHome
,
testObject
.
resource
,
PREVIEW_DIR_NAME
,
'
html.json
'
);
assertConflicts
(
testObject
.
conflicts
,
[
{
local
,
remote
:
local
.
with
({
scheme
:
USER_DATA_SYNC_SCHEME
})
}
]);
assertConflicts
(
testObject
.
conflicts
,
[
local
]);
});
test
(
'
sync removing a snippet - resolve conflict
'
,
async
()
=>
{
...
...
@@ -574,7 +570,7 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
await
testObject
.
accept
Conflict
(
testObject
.
conflicts
[
0
].
local
,
htmlSnippet3
);
await
testObject
.
accept
PreviewContent
(
testObject
.
conflicts
[
0
].
previewResource
,
htmlSnippet3
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -601,7 +597,7 @@ suite('SnippetsSync', () => {
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
await
testObject
.
accept
Conflict
(
testObject
.
conflicts
[
0
].
local
,
''
);
await
testObject
.
accept
PreviewContent
(
testObject
.
conflicts
[
0
].
previewResource
,
''
);
assert
.
equal
(
testObject
.
status
,
SyncStatus
.
Idle
);
assert
.
deepEqual
(
testObject
.
conflicts
,
[]);
...
...
@@ -689,6 +685,22 @@ suite('SnippetsSync', () => {
assert
.
deepEqual
(
actual
,
{
'
typescript.json
'
:
tsSnippet1
,
'
global.code-snippets
'
:
globalSnippet
});
});
test
(
'
previews are reset after all conflicts resolved
'
,
async
()
=>
{
await
updateSnippet
(
'
html.json
'
,
htmlSnippet1
,
client2
);
await
updateSnippet
(
'
typescript.json
'
,
tsSnippet1
,
client2
);
await
client2
.
sync
();
await
updateSnippet
(
'
html.json
'
,
htmlSnippet2
,
testClient
);
await
testObject
.
sync
(
await
testClient
.
manifest
());
let
conflicts
=
testObject
.
conflicts
;
await
testObject
.
acceptPreviewContent
(
conflicts
[
0
].
previewResource
,
htmlSnippet2
);
assert
.
deepEqual
(
testObject
.
resourcePreviews
,
[]);
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
assert
.
ok
(
fileService
.
exists
(
conflicts
[
0
].
previewResource
));
});
function
parseSnippets
(
content
:
string
):
IStringDictionary
<
string
>
{
const
syncData
:
ISyncData
=
JSON
.
parse
(
content
);
return
JSON
.
parse
(
syncData
.
content
);
...
...
@@ -719,8 +731,8 @@ suite('SnippetsSync', () => {
return
null
;
}
function
assertConflicts
(
actual
:
Conflict
[],
expected
:
Conflict
[])
{
assert
.
deepEqual
(
actual
.
map
(({
local
,
remote
})
=>
({
local
:
local
.
toString
(),
remote
:
remote
.
toString
()
})),
expected
.
map
(({
local
,
remote
})
=>
({
local
:
local
.
toString
(),
remote
:
remote
.
toString
()
}
)));
function
assertConflicts
(
actual
:
IResourcePreview
[],
expected
:
URI
[])
{
assert
.
deepEqual
(
actual
.
map
(({
previewResource
})
=>
previewResource
.
toString
()),
expected
.
map
(
uri
=>
uri
.
toString
(
)));
}
});
src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts
浏览文件 @
793c1b28
...
...
@@ -30,7 +30,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import
{
IUserDataAutoSyncService
,
IUserDataSyncService
,
registerConfiguration
,
SyncResource
,
SyncStatus
,
UserDataSyncError
,
UserDataSyncErrorCode
,
USER_DATA_SYNC_SCHEME
,
IUserDataSyncResourceEnablementService
,
SyncResourceConflicts
,
Conflict
,
getSyncResourceFromLocal
Preview
SyncResourceConflicts
,
getSyncResourceFromLocalPreview
,
IResource
Preview
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
FloatingClickWidget
}
from
'
vs/workbench/browser/parts/editor/editorWidgets
'
;
import
{
IWorkbenchContribution
}
from
'
vs/workbench/common/contributions
'
;
...
...
@@ -178,7 +178,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
// close stale conflicts editor previews
if
(
conflictsEditorInputs
.
length
)
{
conflictsEditorInputs
.
forEach
(
input
=>
{
if
(
!
conflicts
.
some
(({
local
})
=>
isEqual
(
local
,
input
.
primary
.
resource
)))
{
if
(
!
conflicts
.
some
(({
previewResource
})
=>
isEqual
(
previewResource
,
input
.
primary
.
resource
)))
{
input
.
dispose
();
}
});
...
...
@@ -238,12 +238,12 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private
async
acceptRemote
(
syncResource
:
SyncResource
,
conflicts
:
Conflict
[])
{
private
async
acceptRemote
(
syncResource
:
SyncResource
,
conflicts
:
IResourcePreview
[])
{
try
{
for
(
const
conflict
of
conflicts
)
{
const
modelRef
=
await
this
.
textModelResolverService
.
createModelReference
(
conflict
.
remote
);
const
modelRef
=
await
this
.
textModelResolverService
.
createModelReference
(
conflict
.
remote
Resource
);
try
{
await
this
.
userDataSyncService
.
accept
Conflict
(
conflict
.
remot
e
,
modelRef
.
object
.
textEditorModel
.
getValue
());
await
this
.
userDataSyncService
.
accept
PreviewContent
(
conflict
.
remoteResourc
e
,
modelRef
.
object
.
textEditorModel
.
getValue
());
}
finally
{
modelRef
.
dispose
();
}
...
...
@@ -253,12 +253,12 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private
async
acceptLocal
(
syncResource
:
SyncResource
,
conflicts
:
Conflict
[]):
Promise
<
void
>
{
private
async
acceptLocal
(
syncResource
:
SyncResource
,
conflicts
:
IResourcePreview
[]):
Promise
<
void
>
{
try
{
for
(
const
conflict
of
conflicts
)
{
const
modelRef
=
await
this
.
textModelResolverService
.
createModelReference
(
conflict
.
local
);
const
modelRef
=
await
this
.
textModelResolverService
.
createModelReference
(
conflict
.
previewResource
);
try
{
await
this
.
userDataSyncService
.
accept
Conflict
(
conflict
.
local
,
modelRef
.
object
.
textEditorModel
.
getValue
());
await
this
.
userDataSyncService
.
accept
PreviewContent
(
conflict
.
previewResource
,
modelRef
.
object
.
textEditorModel
.
getValue
());
}
finally
{
modelRef
.
dispose
();
}
...
...
@@ -625,11 +625,11 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
else
if
(
syncResource
===
SyncResource
.
Keybindings
)
{
label
=
localize
(
'
keybindings conflicts preview
'
,
"
Keybindings Conflicts (Remote ↔ Local)
"
);
}
else
if
(
syncResource
===
SyncResource
.
Snippets
)
{
label
=
localize
(
'
snippets conflicts preview
'
,
"
User Snippet Conflicts (Remote ↔ Local) - {0}
"
,
basename
(
conflict
.
local
));
label
=
localize
(
'
snippets conflicts preview
'
,
"
User Snippet Conflicts (Remote ↔ Local) - {0}
"
,
basename
(
conflict
.
previewResource
));
}
await
this
.
editorService
.
openEditor
({
leftResource
:
conflict
.
remote
,
rightResource
:
conflict
.
local
,
leftResource
:
conflict
.
remote
Resource
,
rightResource
:
conflict
.
previewResource
,
label
,
options
:
{
preserveFocus
:
false
,
...
...
@@ -814,7 +814,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private
registerShowSnippetsConflictsAction
():
void
{
this
.
_snippetsConflictsActionsDisposable
.
clear
();
const
resolveSnippetsConflictsWhenContext
=
ContextKeyExpr
.
regex
(
CONTEXT_CONFLICTS_SOURCES
.
keys
()[
0
],
/.*snippets.*/i
);
const
conflicts
:
Conflict
[]
|
undefined
=
this
.
userDataSyncService
.
conflicts
.
filter
(({
syncResource
})
=>
syncResource
===
SyncResource
.
Snippets
)[
0
]?.
conflicts
;
const
conflicts
:
IResourcePreview
[]
|
undefined
=
this
.
userDataSyncService
.
conflicts
.
filter
(({
syncResource
})
=>
syncResource
===
SyncResource
.
Snippets
)[
0
]?.
conflicts
;
this
.
_snippetsConflictsActionsDisposable
.
add
(
CommandsRegistry
.
registerCommand
(
resolveSnippetsConflictsCommand
.
id
,
()
=>
this
.
handleSyncResourceConflicts
(
SyncResource
.
Snippets
)));
this
.
_snippetsConflictsActionsDisposable
.
add
(
MenuRegistry
.
appendMenuItem
(
MenuId
.
GlobalActivity
,
{
group
:
'
5_sync
'
,
...
...
@@ -1127,11 +1127,11 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
return
false
;
}
if
(
syncResourceConflicts
.
conflicts
.
some
(({
local
})
=>
isEqual
(
local
,
model
.
uri
)))
{
if
(
syncResourceConflicts
.
conflicts
.
some
(({
previewResource
})
=>
isEqual
(
previewResource
,
model
.
uri
)))
{
return
true
;
}
if
(
syncResourceConflicts
.
conflicts
.
some
(({
remote
})
=>
isEqual
(
remot
e
,
model
.
uri
)))
{
if
(
syncResourceConflicts
.
conflicts
.
some
(({
remote
Resource
})
=>
isEqual
(
remoteResourc
e
,
model
.
uri
)))
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
diffEditor.renderSideBySide
'
);
}
...
...
@@ -1142,7 +1142,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
if
(
!
this
.
acceptChangesButton
)
{
const
resource
=
this
.
editor
.
getModel
()
!
.
uri
;
const
syncResourceConflicts
=
this
.
getSyncResourceConflicts
(
resource
)
!
;
const
isRemote
=
syncResourceConflicts
.
conflicts
.
some
(({
remote
})
=>
isEqual
(
remot
e
,
resource
));
const
isRemote
=
syncResourceConflicts
.
conflicts
.
some
(({
remote
Resource
})
=>
isEqual
(
remoteResourc
e
,
resource
));
const
acceptRemoteLabel
=
localize
(
'
accept remote
'
,
"
Accept Remote
"
);
const
acceptLocalLabel
=
localize
(
'
accept local
'
,
"
Accept Local
"
);
this
.
acceptChangesButton
=
this
.
instantiationService
.
createInstance
(
FloatingClickWidget
,
this
.
editor
,
isRemote
?
acceptRemoteLabel
:
acceptLocalLabel
,
null
);
...
...
@@ -1163,11 +1163,11 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
});
if
(
result
.
confirmed
)
{
try
{
await
this
.
userDataSyncService
.
accept
Conflic
t
(
model
.
uri
,
model
.
getValue
());
await
this
.
userDataSyncService
.
accept
PreviewConten
t
(
model
.
uri
,
model
.
getValue
());
}
catch
(
e
)
{
if
(
e
instanceof
UserDataSyncError
&&
e
.
code
===
UserDataSyncErrorCode
.
LocalPreconditionFailed
)
{
const
syncResourceCoflicts
=
this
.
userDataSyncService
.
conflicts
.
filter
(({
syncResource
})
=>
syncResource
===
syncResourceConflicts
.
syncResource
)[
0
];
if
(
syncResourceCoflicts
&&
syncResourceCoflicts
.
conflicts
.
some
(
conflict
=>
isEqual
(
conflict
.
local
,
model
.
uri
)
||
isEqual
(
conflict
.
remot
e
,
model
.
uri
)))
{
if
(
syncResourceCoflicts
&&
syncResourceCoflicts
.
conflicts
.
some
(
conflict
=>
isEqual
(
conflict
.
previewResource
,
model
.
uri
)
||
isEqual
(
conflict
.
remoteResourc
e
,
model
.
uri
)))
{
this
.
notificationService
.
warn
(
localize
(
'
update conflicts
'
,
"
Could not resolve conflicts as there is new local version available. Please try again.
"
));
}
}
else
{
...
...
@@ -1183,7 +1183,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
}
private
getSyncResourceConflicts
(
resource
:
URI
):
SyncResourceConflicts
|
undefined
{
return
this
.
userDataSyncService
.
conflicts
.
filter
(({
conflicts
})
=>
conflicts
.
some
(({
local
,
remote
})
=>
isEqual
(
local
,
resource
)
||
isEqual
(
remot
e
,
resource
)))[
0
];
return
this
.
userDataSyncService
.
conflicts
.
filter
(({
conflicts
})
=>
conflicts
.
some
(({
previewResource
,
remoteResource
})
=>
isEqual
(
previewResource
,
resource
)
||
isEqual
(
remoteResourc
e
,
resource
)))[
0
];
}
private
disposeAcceptChangesWidgetRenderer
():
void
{
...
...
src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts
浏览文件 @
793c1b28
...
...
@@ -103,8 +103,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return
this
.
channel
.
call
(
'
isFirstTimeSyncingWithAnotherMachine
'
);
}
accept
Conflict
(
conflict
:
URI
,
content
:
string
):
Promise
<
void
>
{
return
this
.
channel
.
call
(
'
accept
Conflict
'
,
[
conflict
,
content
]);
accept
PreviewContent
(
resource
:
URI
,
content
:
string
):
Promise
<
void
>
{
return
this
.
channel
.
call
(
'
accept
PreviewContent
'
,
[
resource
,
content
]);
}
resolveContent
(
resource
:
URI
):
Promise
<
string
|
null
>
{
...
...
@@ -140,8 +140,13 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
this
.
_conflicts
=
conflicts
.
map
(
c
=>
({
syncResource
:
c
.
syncResource
,
conflicts
:
c
.
conflicts
.
map
(({
local
,
remote
})
=>
({
local
:
URI
.
revive
(
local
),
remote
:
URI
.
revive
(
remote
)
}))
conflicts
:
c
.
conflicts
.
map
(
r
=>
({
...
r
,
localResource
:
URI
.
revive
(
r
.
localResource
),
remoteResource
:
URI
.
revive
(
r
.
remoteResource
),
previewResource
:
URI
.
revive
(
r
.
previewResource
),
}))
}));
this
.
_onDidChangeConflicts
.
fire
(
conflicts
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录