Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
58819485
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,发现更多精彩内容 >>
提交
58819485
编写于
3月 30, 2020
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix #91545
上级
21293c42
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
132 addition
and
68 deletion
+132
-68
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
+13
-4
src/vs/platform/userDataSync/common/extensionsSync.ts
src/vs/platform/userDataSync/common/extensionsSync.ts
+28
-11
src/vs/platform/userDataSync/common/globalStateSync.ts
src/vs/platform/userDataSync/common/globalStateSync.ts
+19
-10
src/vs/platform/userDataSync/common/keybindingsSync.ts
src/vs/platform/userDataSync/common/keybindingsSync.ts
+1
-1
src/vs/platform/userDataSync/common/settingsSync.ts
src/vs/platform/userDataSync/common/settingsSync.ts
+1
-1
src/vs/platform/userDataSync/common/snippetsSync.ts
src/vs/platform/userDataSync/common/snippetsSync.ts
+28
-15
src/vs/platform/userDataSync/common/userDataSync.ts
src/vs/platform/userDataSync/common/userDataSync.ts
+6
-0
src/vs/platform/userDataSync/common/userDataSyncService.ts
src/vs/platform/userDataSync/common/userDataSyncService.ts
+10
-1
src/vs/platform/userDataSync/test/common/synchronizer.test.ts
...vs/platform/userDataSync/test/common/synchronizer.test.ts
+5
-1
src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts
...form/userDataSync/test/common/userDataSyncService.test.ts
+21
-24
未找到文件。
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
浏览文件 @
58819485
...
...
@@ -7,7 +7,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
import
{
IFileService
,
IFileContent
,
FileChangesEvent
,
FileOperationResult
,
FileOperationError
}
from
'
vs/platform/files/common/files
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
SyncResource
,
SyncStatus
,
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
UserDataSyncError
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
Conflict
,
ISyncResourceHandle
,
USER_DATA_SYNC_SCHEME
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
SyncResource
,
SyncStatus
,
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
UserDataSyncError
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
Conflict
,
ISyncResourceHandle
,
USER_DATA_SYNC_SCHEME
,
ISyncPreviewResult
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
joinPath
,
dirname
,
isEqual
,
basename
}
from
'
vs/base/common/resources
'
;
import
{
CancelablePromise
}
from
'
vs/base/common/async
'
;
...
...
@@ -144,6 +144,16 @@ export abstract class AbstractSynchroniser extends Disposable {
}
}
async
getSyncPreview
():
Promise
<
ISyncPreviewResult
>
{
if
(
!
this
.
isEnabled
())
{
return
{
hasLocalChanged
:
false
,
hasRemoteChanged
:
false
};
}
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
return
this
.
getPreview
(
remoteUserData
,
lastSyncUserData
);
}
protected
async
doSync
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
SyncStatus
>
{
if
(
remoteUserData
.
syncData
&&
remoteUserData
.
syncData
.
version
>
this
.
version
)
{
// current version is not compatible with cloud version
...
...
@@ -285,15 +295,14 @@ export abstract class AbstractSynchroniser extends Disposable {
protected
abstract
readonly
version
:
number
;
protected
abstract
performSync
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
SyncStatus
>
;
protected
abstract
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
ISyncPreviewResult
>
;
}
export
interface
IFileSyncPreviewResult
{
export
interface
IFileSyncPreviewResult
extends
ISyncPreviewResult
{
readonly
fileContent
:
IFileContent
|
null
;
readonly
remoteUserData
:
IRemoteUserData
;
readonly
lastSyncUserData
:
IRemoteUserData
|
null
;
readonly
content
:
string
|
null
;
readonly
hasLocalChanged
:
boolean
;
readonly
hasRemoteChanged
:
boolean
;
readonly
hasConflicts
:
boolean
;
}
...
...
src/vs/platform/userDataSync/common/extensionsSync.ts
浏览文件 @
58819485
...
...
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
SyncStatus
,
IUserDataSyncStoreService
,
ISyncExtension
,
IUserDataSyncLogService
,
IUserDataSynchroniser
,
SyncResource
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
ISyncResourceHandle
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
SyncStatus
,
IUserDataSyncStoreService
,
ISyncExtension
,
IUserDataSyncLogService
,
IUserDataSynchroniser
,
SyncResource
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
ISyncResourceHandle
,
ISyncPreviewResult
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IExtensionManagementService
,
IExtensionGalleryService
,
IGlobalExtensionEnablementService
}
from
'
vs/platform/extensionManagement/common/extensionManagement
'
;
...
...
@@ -20,7 +20,7 @@ import { joinPath, dirname, basename } from 'vs/base/common/resources';
import
{
format
}
from
'
vs/base/common/jsonFormatter
'
;
import
{
applyEdits
}
from
'
vs/base/common/jsonEdit
'
;
interface
ISyncPreviewResult
{
interface
I
ExtensionsSyncPreviewResult
extends
I
SyncPreviewResult
{
readonly
localExtensions
:
ISyncExtension
[];
readonly
remoteUserData
:
IRemoteUserData
;
readonly
lastSyncUserData
:
ILastSyncUserData
|
null
;
...
...
@@ -82,7 +82,11 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const
localExtensions
=
await
this
.
getLocalExtensions
();
const
remoteExtensions
=
this
.
parseExtensions
(
remoteUserData
.
syncData
);
const
{
added
,
updated
,
remote
,
removed
}
=
merge
(
localExtensions
,
remoteExtensions
,
localExtensions
,
[],
this
.
getIgnoredExtensions
());
await
this
.
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
localExtensions
,
skippedExtensions
:
[],
lastSyncUserData
});
await
this
.
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
localExtensions
,
skippedExtensions
:
[],
lastSyncUserData
,
hasLocalChanged
:
added
.
length
>
0
||
removed
.
length
>
0
||
updated
.
length
>
0
,
hasRemoteChanged
:
remote
!==
null
});
}
// No remote exists to pull
...
...
@@ -112,7 +116,11 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const
{
added
,
removed
,
updated
,
remote
}
=
merge
(
localExtensions
,
null
,
null
,
[],
this
.
getIgnoredExtensions
());
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
<
ILastSyncUserData
>
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
await
this
.
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
localExtensions
,
skippedExtensions
:
[],
lastSyncUserData
},
true
);
await
this
.
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
localExtensions
,
skippedExtensions
:
[],
lastSyncUserData
,
hasLocalChanged
:
added
.
length
>
0
||
removed
.
length
>
0
||
updated
.
length
>
0
,
hasRemoteChanged
:
remote
!==
null
},
true
);
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: Finished pushing extensions.`
);
}
finally
{
...
...
@@ -168,7 +176,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
return
SyncStatus
.
Idle
;
}
pr
ivate
async
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
ILastSyncUserData
|
null
):
Promise
<
I
SyncPreviewResult
>
{
pr
otected
async
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
ILastSyncUserData
|
null
):
Promise
<
IExtensions
SyncPreviewResult
>
{
const
remoteExtensions
:
ISyncExtension
[]
|
null
=
remoteUserData
.
syncData
?
this
.
parseExtensions
(
remoteUserData
.
syncData
)
:
null
;
const
lastSyncExtensions
:
ISyncExtension
[]
|
null
=
lastSyncUserData
?
this
.
parseExtensions
(
lastSyncUserData
.
syncData
!
)
:
null
;
const
skippedExtensions
:
ISyncExtension
[]
=
lastSyncUserData
?
lastSyncUserData
.
skippedExtensions
||
[]
:
[];
...
...
@@ -183,22 +191,31 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const
{
added
,
removed
,
updated
,
remote
}
=
merge
(
localExtensions
,
remoteExtensions
,
lastSyncExtensions
,
skippedExtensions
,
this
.
getIgnoredExtensions
());
return
{
added
,
removed
,
updated
,
remote
,
skippedExtensions
,
remoteUserData
,
localExtensions
,
lastSyncUserData
};
return
{
added
,
removed
,
updated
,
remote
,
skippedExtensions
,
remoteUserData
,
localExtensions
,
lastSyncUserData
,
hasLocalChanged
:
added
.
length
>
0
||
removed
.
length
>
0
||
updated
.
length
>
0
,
hasRemoteChanged
:
remote
!==
null
};
}
private
getIgnoredExtensions
()
{
return
this
.
configurationService
.
getValue
<
string
[]
>
(
'
sync.ignoredExtensions
'
)
||
[];
}
private
async
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
skippedExtensions
,
lastSyncUserData
,
localExtensions
}:
I
SyncPreviewResult
,
forcePush
?:
boolean
):
Promise
<
void
>
{
private
async
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
skippedExtensions
,
lastSyncUserData
,
localExtensions
,
hasLocalChanged
,
hasRemoteChanged
}:
IExtensions
SyncPreviewResult
,
forcePush
?:
boolean
):
Promise
<
void
>
{
const
hasChanges
=
added
.
length
||
removed
.
length
||
updated
.
length
||
remote
;
if
(
!
hasChanges
)
{
if
(
!
hasLocalChanged
&&
!
hasRemoteChanged
)
{
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: No changes found during synchronizing extensions.`
);
}
if
(
added
.
length
||
removed
.
length
||
updated
.
length
)
{
if
(
hasLocalChanged
)
{
// back up all disabled or market place extensions
const
backUpExtensions
=
localExtensions
.
filter
(
e
=>
e
.
disabled
||
!!
e
.
identifier
.
uuid
);
await
this
.
backupLocal
(
JSON
.
stringify
(
backUpExtensions
));
...
...
src/vs/platform/userDataSync/common/globalStateSync.ts
浏览文件 @
58819485
...
...
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IGlobalState
,
SyncResource
,
IUserDataSynchroniser
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
ISyncResourceHandle
,
IStorageValue
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IGlobalState
,
SyncResource
,
IUserDataSynchroniser
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
ISyncResourceHandle
,
IStorageValue
,
ISyncPreviewResult
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
...
...
@@ -25,7 +25,7 @@ import { IStorageKeysSyncRegistryService, IStorageKey } from 'vs/platform/userDa
const
argvStoragePrefx
=
'
globalState.argv.
'
;
const
argvProperties
:
string
[]
=
[
'
locale
'
];
interface
ISyncPreviewResult
{
interface
I
GlobalSyncPreviewResult
extends
I
SyncPreviewResult
{
readonly
local
:
{
added
:
IStringDictionary
<
IStorageValue
>
,
removed
:
string
[],
updated
:
IStringDictionary
<
IStorageValue
>
};
readonly
remote
:
IStringDictionary
<
IStorageValue
>
|
null
;
readonly
localUserData
:
IGlobalState
;
...
...
@@ -74,7 +74,11 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
const
localGlobalState
=
await
this
.
getLocalGlobalState
();
const
remoteGlobalState
:
IGlobalState
=
JSON
.
parse
(
remoteUserData
.
syncData
.
content
);
const
{
local
,
remote
}
=
merge
(
localGlobalState
.
storage
,
remoteGlobalState
.
storage
,
null
,
this
.
getSyncStorageKeys
(),
this
.
logService
);
await
this
.
apply
({
local
,
remote
,
remoteUserData
,
localUserData
:
localGlobalState
,
lastSyncUserData
});
await
this
.
apply
({
local
,
remote
,
remoteUserData
,
localUserData
:
localGlobalState
,
lastSyncUserData
,
hasLocalChanged
:
Object
.
keys
(
local
.
added
).
length
>
0
||
Object
.
keys
(
local
.
updated
).
length
>
0
||
local
.
removed
.
length
>
0
,
hasRemoteChanged
:
remote
!==
null
});
}
// No remote exists to pull
...
...
@@ -103,7 +107,11 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
const
localUserData
=
await
this
.
getLocalGlobalState
();
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
await
this
.
apply
({
local
:
{
added
:
{},
removed
:
[],
updated
:
{}
},
remote
:
localUserData
.
storage
,
remoteUserData
,
localUserData
,
lastSyncUserData
},
true
);
await
this
.
apply
({
local
:
{
added
:
{},
removed
:
[],
updated
:
{}
},
remote
:
localUserData
.
storage
,
remoteUserData
,
localUserData
,
lastSyncUserData
,
hasLocalChanged
:
false
,
hasRemoteChanged
:
true
},
true
);
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: Finished pushing UI State.`
);
}
finally
{
...
...
@@ -159,7 +167,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
return
SyncStatus
.
Idle
;
}
pr
ivate
async
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
I
SyncPreviewResult
>
{
pr
otected
async
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
IGlobal
SyncPreviewResult
>
{
const
remoteGlobalState
:
IGlobalState
=
remoteUserData
.
syncData
?
JSON
.
parse
(
remoteUserData
.
syncData
.
content
)
:
null
;
const
lastSyncGlobalState
:
IGlobalState
=
lastSyncUserData
&&
lastSyncUserData
.
syncData
?
JSON
.
parse
(
lastSyncUserData
.
syncData
.
content
)
:
null
;
...
...
@@ -173,13 +181,14 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
const
{
local
,
remote
}
=
merge
(
localGloablState
.
storage
,
remoteGlobalState
?
remoteGlobalState
.
storage
:
null
,
lastSyncGlobalState
?
lastSyncGlobalState
.
storage
:
null
,
this
.
getSyncStorageKeys
(),
this
.
logService
);
return
{
local
,
remote
,
remoteUserData
,
localUserData
:
localGloablState
,
lastSyncUserData
};
return
{
local
,
remote
,
remoteUserData
,
localUserData
:
localGloablState
,
lastSyncUserData
,
hasLocalChanged
:
Object
.
keys
(
local
.
added
).
length
>
0
||
Object
.
keys
(
local
.
updated
).
length
>
0
||
local
.
removed
.
length
>
0
,
hasRemoteChanged
:
remote
!==
null
};
}
private
async
apply
({
local
,
remote
,
remoteUserData
,
lastSyncUserData
,
localUserData
}:
ISyncPreviewResult
,
forcePush
?:
boolean
):
Promise
<
void
>
{
const
hasLocalChanged
=
Object
.
keys
(
local
.
added
).
length
>
0
||
Object
.
keys
(
local
.
updated
).
length
>
0
||
local
.
removed
.
length
>
0
;
const
hasRemoteChanged
=
remote
!==
null
;
private
async
apply
({
local
,
remote
,
remoteUserData
,
lastSyncUserData
,
localUserData
,
hasLocalChanged
,
hasRemoteChanged
}:
IGlobalSyncPreviewResult
,
forcePush
?:
boolean
):
Promise
<
void
>
{
if
(
!
hasLocalChanged
&&
!
hasRemoteChanged
)
{
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: No changes found during synchronizing ui state.`
);
...
...
src/vs/platform/userDataSync/common/keybindingsSync.ts
浏览文件 @
58819485
...
...
@@ -258,7 +258,7 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
this
.
syncPreviewResultPromise
=
null
;
}
pr
ivate
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
IFileSyncPreviewResult
>
{
pr
otected
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
IFileSyncPreviewResult
>
{
if
(
!
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
=
createCancelablePromise
(
token
=>
this
.
generatePreview
(
remoteUserData
,
lastSyncUserData
,
token
));
}
...
...
src/vs/platform/userDataSync/common/settingsSync.ts
浏览文件 @
58819485
...
...
@@ -309,7 +309,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser {
this
.
syncPreviewResultPromise
=
null
;
}
pr
ivate
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
,
resolvedConflicts
:
{
key
:
string
,
value
:
any
}
[]):
Promise
<
IFileSyncPreviewResult
>
{
pr
otected
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
,
resolvedConflicts
:
{
key
:
string
,
value
:
any
}[]
=
[]):
Promise
<
IFileSyncPreviewResult
>
{
if
(
!
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
=
createCancelablePromise
(
token
=>
this
.
generatePreview
(
remoteUserData
,
lastSyncUserData
,
resolvedConflicts
,
token
));
}
...
...
src/vs/platform/userDataSync/common/snippetsSync.ts
浏览文件 @
58819485
...
...
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IUserDataSynchroniser
,
SyncResource
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
Conflict
,
USER_DATA_SYNC_SCHEME
,
PREVIEW_DIR_NAME
,
UserDataSyncError
,
UserDataSyncErrorCode
,
ISyncResourceHandle
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IUserDataSynchroniser
,
SyncResource
,
IUserDataSyncEnablementService
,
IUserDataSyncBackupStoreService
,
Conflict
,
USER_DATA_SYNC_SCHEME
,
PREVIEW_DIR_NAME
,
UserDataSyncError
,
UserDataSyncErrorCode
,
ISyncResourceHandle
,
ISyncPreviewResult
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IFileService
,
FileChangesEvent
,
IFileStat
,
IFileContent
,
FileOperationError
,
FileOperationResult
}
from
'
vs/platform/files/common/files
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
...
...
@@ -17,7 +17,7 @@ import { merge } from 'vs/platform/userDataSync/common/snippetsMerge';
import
{
CancelablePromise
,
createCancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
interface
ISyncPreviewResult
{
interface
IS
inppetsSyncPreviewResult
extends
IS
yncPreviewResult
{
readonly
local
:
IStringDictionary
<
IFileContent
>
;
readonly
remoteUserData
:
IRemoteUserData
;
readonly
lastSyncUserData
:
IRemoteUserData
|
null
;
...
...
@@ -34,7 +34,7 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
protected
readonly
version
:
number
=
1
;
private
readonly
snippetsFolder
:
URI
;
private
readonly
snippetsPreviewFolder
:
URI
;
private
syncPreviewResultPromise
:
CancelablePromise
<
ISyncPreviewResult
>
|
null
=
null
;
private
syncPreviewResultPromise
:
CancelablePromise
<
IS
inppetsS
yncPreviewResult
>
|
null
=
null
;
constructor
(
@
IEnvironmentService
environmentService
:
IEnvironmentService
,
...
...
@@ -94,8 +94,10 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
const
localSnippets
=
this
.
toSnippetsContents
(
local
);
const
remoteSnippets
=
this
.
parseSnippets
(
remoteUserData
.
syncData
);
const
{
added
,
updated
,
remote
,
removed
}
=
merge
(
localSnippets
,
remoteSnippets
,
localSnippets
);
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISyncPreviewResult
>
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
local
,
lastSyncUserData
,
conflicts
:
[],
resolvedConflicts
:
{}
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISinppetsSyncPreviewResult
>
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
local
,
lastSyncUserData
,
conflicts
:
[],
resolvedConflicts
:
{},
hasLocalChanged
:
Object
.
keys
(
added
).
length
>
0
||
removed
.
length
>
0
||
Object
.
keys
(
updated
).
length
>
0
,
hasRemoteChanged
:
remote
!==
null
}));
await
this
.
apply
();
}
...
...
@@ -128,8 +130,10 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
const
{
added
,
removed
,
updated
,
remote
}
=
merge
(
localSnippets
,
null
,
null
);
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISyncPreviewResult
>
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
local
,
lastSyncUserData
,
conflicts
:
[],
resolvedConflicts
:
{}
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISinppetsSyncPreviewResult
>
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
local
,
lastSyncUserData
,
conflicts
:
[],
resolvedConflicts
:
{},
hasLocalChanged
:
Object
.
keys
(
added
).
length
>
0
||
removed
.
length
>
0
||
Object
.
keys
(
updated
).
length
>
0
,
hasRemoteChanged
:
remote
!==
null
}));
await
this
.
apply
(
true
);
...
...
@@ -252,7 +256,7 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
}
}
pr
ivate
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
I
SyncPreviewResult
>
{
pr
otected
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
ISinppets
SyncPreviewResult
>
{
if
(
!
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
=
createCancelablePromise
(
token
=>
this
.
getSnippetsFileContents
()
.
then
(
local
=>
this
.
generatePreview
(
local
,
remoteUserData
,
lastSyncUserData
,
{},
token
)));
...
...
@@ -274,7 +278,7 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
}
}
private
async
generatePreview
(
local
:
IStringDictionary
<
IFileContent
>
,
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
,
resolvedConflicts
:
IStringDictionary
<
string
|
null
>
,
token
:
CancellationToken
):
Promise
<
ISyncPreviewResult
>
{
private
async
generatePreview
(
local
:
IStringDictionary
<
IFileContent
>
,
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
,
resolvedConflicts
:
IStringDictionary
<
string
|
null
>
,
token
:
CancellationToken
):
Promise
<
IS
inppetsS
yncPreviewResult
>
{
const
localSnippets
=
this
.
toSnippetsContents
(
local
);
const
remoteSnippets
:
IStringDictionary
<
string
>
|
null
=
remoteUserData
.
syncData
?
this
.
parseSnippets
(
remoteUserData
.
syncData
)
:
null
;
const
lastSyncSnippets
:
IStringDictionary
<
string
>
|
null
=
lastSyncUserData
?
this
.
parseSnippets
(
lastSyncUserData
.
syncData
!
)
:
null
;
...
...
@@ -309,7 +313,18 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
}
}
return
{
remoteUserData
,
local
,
lastSyncUserData
,
added
:
mergeResult
.
added
,
removed
:
mergeResult
.
removed
,
updated
:
mergeResult
.
updated
,
conflicts
,
remote
:
mergeResult
.
remote
,
resolvedConflicts
};
return
{
remoteUserData
,
local
,
lastSyncUserData
,
added
:
mergeResult
.
added
,
removed
:
mergeResult
.
removed
,
updated
:
mergeResult
.
updated
,
conflicts
,
remote
:
mergeResult
.
remote
,
resolvedConflicts
,
hasLocalChanged
:
Object
.
keys
(
mergeResult
.
added
).
length
>
0
||
mergeResult
.
removed
.
length
>
0
||
Object
.
keys
(
mergeResult
.
updated
).
length
>
0
,
hasRemoteChanged
:
mergeResult
.
remote
!==
null
};
}
private
async
apply
(
forcePush
?:
boolean
):
Promise
<
void
>
{
...
...
@@ -317,15 +332,13 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
return
;
}
let
{
added
,
removed
,
updated
,
local
,
remote
,
remoteUserData
,
lastSyncUserData
}
=
await
this
.
syncPreviewResultPromise
;
let
{
added
,
removed
,
updated
,
local
,
remote
,
remoteUserData
,
lastSyncUserData
,
hasLocalChanged
,
hasRemoteChanged
}
=
await
this
.
syncPreviewResultPromise
;
const
hasChanges
=
Object
.
keys
(
added
).
length
||
removed
.
length
||
Object
.
keys
(
updated
).
length
||
remote
;
if
(
!
hasChanges
)
{
if
(
!
hasLocalChanged
&&
!
hasRemoteChanged
)
{
this
.
logService
.
info
(
`
${
this
.
syncResourceLogLabel
}
: No changes found during synchronizing snippets.`
);
}
if
(
Object
.
keys
(
added
).
length
||
removed
.
length
||
Object
.
keys
(
updated
).
length
)
{
if
(
hasLocalChanged
)
{
// back up all snippets
await
this
.
backupLocal
(
JSON
.
stringify
(
this
.
toSnippetsContents
(
local
)));
await
this
.
updateLocalSnippets
(
added
,
removed
,
updated
,
local
);
...
...
src/vs/platform/userDataSync/common/userDataSync.ts
浏览文件 @
58819485
...
...
@@ -254,6 +254,11 @@ export interface ISyncResourceHandle {
export
type
Conflict
=
{
remote
:
URI
,
local
:
URI
};
export
interface
ISyncPreviewResult
{
readonly
hasLocalChanged
:
boolean
;
readonly
hasRemoteChanged
:
boolean
;
}
export
interface
IUserDataSynchroniser
{
readonly
resource
:
SyncResource
;
...
...
@@ -268,6 +273,7 @@ export interface IUserDataSynchroniser {
sync
(
ref
?:
string
):
Promise
<
void
>
;
stop
():
Promise
<
void
>
;
getSyncPreview
():
Promise
<
ISyncPreviewResult
>
hasPreviouslySynced
():
Promise
<
boolean
>
hasLocalData
():
Promise
<
boolean
>
;
resetLocal
():
Promise
<
void
>
;
...
...
src/vs/platform/userDataSync/common/userDataSyncService.ts
浏览文件 @
58819485
...
...
@@ -217,7 +217,16 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
if
(
await
this
.
hasPreviouslySynced
())
{
return
false
;
}
return
await
this
.
hasLocalData
();
if
(
!
(
await
this
.
hasLocalData
()))
{
return
false
;
}
for
(
const
synchroniser
of
this
.
synchronisers
)
{
const
preview
=
await
synchroniser
.
getSyncPreview
();
if
(
preview
.
hasLocalChanged
||
preview
.
hasRemoteChanged
)
{
return
true
;
}
}
return
false
;
}
async
reset
():
Promise
<
void
>
{
...
...
src/vs/platform/userDataSync/test/common/synchronizer.test.ts
浏览文件 @
58819485
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
IUserDataSyncStoreService
,
SyncResource
,
SyncStatus
,
IUserDataSyncEnablementService
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IUserDataSyncStoreService
,
SyncResource
,
SyncStatus
,
IUserDataSyncEnablementService
,
ISyncPreviewResult
}
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
{
AbstractSynchroniser
,
IRemoteUserData
}
from
'
vs/platform/userDataSync/common/abstractSynchronizer
'
;
...
...
@@ -49,6 +49,10 @@ class TestSynchroniser extends AbstractSynchroniser {
this
.
syncBarrier
.
open
();
}
protected
async
getPreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
IRemoteUserData
|
null
):
Promise
<
ISyncPreviewResult
>
{
return
{
hasLocalChanged
:
false
,
hasRemoteChanged
:
false
};
}
}
suite
(
'
TestSynchronizer
'
,
()
=>
{
...
...
src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts
浏览文件 @
58819485
...
...
@@ -103,17 +103,18 @@ suite('UserDataSyncService', () => {
await
testObject
.
pull
();
assert
.
deepEqual
(
target
.
requests
,
[
/
/ Manifest
/
* first time sync */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
// Snippets
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets/latest`
,
headers
:
{}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
/* pull */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
...
...
@@ -143,17 +144,14 @@ suite('UserDataSyncService', () => {
await
testObject
.
pull
();
assert
.
deepEqual
(
target
.
requests
,
[
/
/ Manifest
/
* first time sync */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
// Keybindings
/* pull */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
// Snippets
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets/latest`
,
headers
:
{}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
...
...
@@ -178,18 +176,19 @@ suite('UserDataSyncService', () => {
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
/
/ Manifest
/
* first time sync */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
/* sync */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
// Snippets
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets/latest`
,
headers
:
{}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
...
...
@@ -220,21 +219,19 @@ suite('UserDataSyncService', () => {
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
/
/ Manifest
/
* first time sync */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
/* first time sync */
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
// Snippets
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets/latest`
,
headers
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/snippets`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录