Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
d022bb76
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,体验更适合开发者的 AI 搜索 >>
提交
d022bb76
编写于
2月 09, 2020
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
move common logic to abstract synchronizer
上级
dcef03a8
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
186 addition
and
244 deletion
+186
-244
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
+101
-9
src/vs/platform/userDataSync/common/extensionsSync.ts
src/vs/platform/userDataSync/common/extensionsSync.ts
+23
-32
src/vs/platform/userDataSync/common/globalStateSync.ts
src/vs/platform/userDataSync/common/globalStateSync.ts
+21
-34
src/vs/platform/userDataSync/common/keybindingsSync.ts
src/vs/platform/userDataSync/common/keybindingsSync.ts
+19
-81
src/vs/platform/userDataSync/common/settingsSync.ts
src/vs/platform/userDataSync/common/settingsSync.ts
+22
-88
未找到文件。
src/vs/platform/userDataSync/common/abstractSynchronizer.ts
浏览文件 @
d022bb76
...
...
@@ -7,13 +7,15 @@ import { Disposable } from 'vs/base/common/lifecycle';
import
{
IFileService
,
IFileContent
,
FileChangesEvent
,
FileSystemProviderError
,
FileSystemProviderErrorCode
,
FileOperationResult
,
FileOperationError
}
from
'
vs/platform/files/common/files
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
SyncSource
,
SyncStatus
,
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
UserDataSyncError
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
SyncSource
,
SyncStatus
,
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
UserDataSyncError
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
joinPath
,
dirname
}
from
'
vs/base/common/resources
'
;
import
{
toLocalISOString
}
from
'
vs/base/common/date
'
;
import
{
ThrottledDelayer
}
from
'
vs/base/common/async
'
;
import
{
ThrottledDelayer
,
CancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
ParseError
,
parse
}
from
'
vs/base/common/json
'
;
import
{
FormattingOptions
}
from
'
vs/base/common/jsonFormatter
'
;
type
SyncConflictsClassification
=
{
source
?:
{
classification
:
'
SystemMetaData
'
,
purpose
:
'
FeatureInsight
'
,
isMeasurement
:
true
};
...
...
@@ -40,6 +42,7 @@ export abstract class AbstractSynchroniser extends Disposable {
@
IEnvironmentService
environmentService
:
IEnvironmentService
,
@
IUserDataSyncStoreService
protected
readonly
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
ITelemetryService
private
readonly
telemetryService
:
ITelemetryService
,
@
IUserDataSyncLogService
protected
readonly
logService
:
IUserDataSyncLogService
,
)
{
super
();
this
.
syncFolder
=
joinPath
(
environmentService
.
userDataSyncHome
,
source
);
...
...
@@ -63,6 +66,21 @@ export abstract class AbstractSynchroniser extends Disposable {
}
}
async
sync
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
`
${
this
.
source
}
: Skipping synchronizing
${
this
.
source
.
toLowerCase
()}
as it is disabled.`
);
return
;
}
if
(
this
.
status
!==
SyncStatus
.
Idle
)
{
this
.
logService
.
info
(
`
${
this
.
source
}
: Skipping synchronizing
${
this
.
source
.
toLowerCase
()}
as it is running already.`
);
return
;
}
this
.
logService
.
trace
(
`
${
this
.
source
}
: Started synchronizing
${
this
.
source
.
toLowerCase
()}
...`
);
this
.
setStatus
(
SyncStatus
.
Syncing
);
return
this
.
doSync
();
}
async
hasPreviouslySynced
():
Promise
<
boolean
>
{
const
lastSyncData
=
await
this
.
getLastSyncUserData
();
return
!!
lastSyncData
;
...
...
@@ -74,6 +92,12 @@ export abstract class AbstractSynchroniser extends Disposable {
return
remoteUserData
.
content
!==
null
;
}
async
getRemoteContent
():
Promise
<
string
|
null
>
{
const
lastSyncData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncData
);
return
remoteUserData
.
content
;
}
async
resetLocal
():
Promise
<
void
>
{
try
{
await
this
.
fileService
.
del
(
this
.
lastSyncResource
);
...
...
@@ -94,11 +118,11 @@ export abstract class AbstractSynchroniser extends Disposable {
}
protected
async
getRemoteUserData
(
lastSyncData
:
IUserData
|
null
):
Promise
<
IUserData
>
{
return
this
.
userDataSyncStoreService
.
read
(
this
.
getRemoteDataResourceKey
()
,
lastSyncData
,
this
.
source
);
return
this
.
userDataSyncStoreService
.
read
(
this
.
remoteDataResourceKey
,
lastSyncData
,
this
.
source
);
}
protected
async
updateRemoteUserData
(
content
:
string
,
ref
:
string
|
null
):
Promise
<
string
>
{
return
this
.
userDataSyncStoreService
.
write
(
this
.
getRemoteDataResourceKey
()
,
content
,
ref
,
this
.
source
);
return
this
.
userDataSyncStoreService
.
write
(
this
.
remoteDataResourceKey
,
content
,
ref
,
this
.
source
);
}
protected
async
backupLocal
(
content
:
VSBuffer
):
Promise
<
void
>
{
...
...
@@ -117,24 +141,55 @@ export abstract class AbstractSynchroniser extends Disposable {
}
protected
abstract
readonly
enabled
:
boolean
;
protected
abstract
getRemoteDataResourceKey
():
string
;
protected
abstract
readonly
remoteDataResourceKey
:
string
;
protected
abstract
doSync
():
Promise
<
void
>
;
}
export
interface
IFileSyncPreviewResult
{
readonly
fileContent
:
IFileContent
|
null
;
readonly
remoteUserData
:
IUserData
;
readonly
lastSyncUserData
:
IUserData
|
null
;
readonly
content
:
string
|
null
;
readonly
hasLocalChanged
:
boolean
;
readonly
hasRemoteChanged
:
boolean
;
readonly
hasConflicts
:
boolean
;
}
export
abstract
class
AbstractFileSynchroniser
extends
AbstractSynchroniser
{
protected
syncPreviewResultPromise
:
CancelablePromise
<
IFileSyncPreviewResult
>
|
null
=
null
;
constructor
(
protected
readonly
file
:
URI
,
readonly
source
:
SyncSource
,
source
:
SyncSource
,
@
IFileService
fileService
:
IFileService
,
@
IEnvironmentService
environmentService
:
IEnvironmentService
,
@
IUserDataSyncStoreService
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
@
IUserDataSyncLogService
logService
:
IUserDataSyncLogService
,
)
{
super
(
source
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
);
super
(
source
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
,
logService
);
this
.
_register
(
this
.
fileService
.
watch
(
dirname
(
file
)));
this
.
_register
(
this
.
fileService
.
onFileChanges
(
e
=>
this
.
onFileChanges
(
e
)));
}
async
stop
():
Promise
<
void
>
{
this
.
cancel
();
this
.
logService
.
trace
(
`
${
this
.
source
}
: Stopped synchronizing
${
this
.
source
.
toLowerCase
()}
.`
);
await
this
.
fileService
.
del
(
this
.
conflictsPreviewResource
);
this
.
setStatus
(
SyncStatus
.
Idle
);
}
async
getRemoteContent
(
preview
?:
boolean
):
Promise
<
string
|
null
>
{
if
(
preview
)
{
if
(
this
.
syncPreviewResultPromise
)
{
const
result
=
await
this
.
syncPreviewResultPromise
;
return
result
.
remoteUserData
?
result
.
remoteUserData
.
content
:
null
;
}
}
return
super
.
getRemoteContent
();
}
protected
async
getLocalFileContent
():
Promise
<
IFileContent
|
null
>
{
try
{
return
await
this
.
fileService
.
readFile
(
this
.
file
);
...
...
@@ -182,6 +237,43 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
}
protected
abstract
cancel
():
void
;
protected
abstract
doSync
():
Promise
<
void
>
;
protected
cancel
():
void
{
if
(
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
.
cancel
();
this
.
syncPreviewResultPromise
=
null
;
}
}
protected
abstract
readonly
conflictsPreviewResource
:
URI
;
}
export
abstract
class
AbstractJsonFileSynchroniser
extends
AbstractFileSynchroniser
{
constructor
(
file
:
URI
,
source
:
SyncSource
,
@
IFileService
fileService
:
IFileService
,
@
IEnvironmentService
environmentService
:
IEnvironmentService
,
@
IUserDataSyncStoreService
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
@
IUserDataSyncLogService
logService
:
IUserDataSyncLogService
,
@
IUserDataSyncUtilService
protected
readonly
userDataSyncUtilService
:
IUserDataSyncUtilService
,
)
{
super
(
file
,
source
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
,
logService
);
}
protected
hasErrors
(
content
:
string
):
boolean
{
const
parseErrors
:
ParseError
[]
=
[];
parse
(
content
,
parseErrors
,
{
allowEmptyContent
:
true
,
allowTrailingComma
:
true
});
return
parseErrors
.
length
>
0
;
}
private
_formattingOptions
:
Promise
<
FormattingOptions
>
|
undefined
=
undefined
;
protected
getFormattingOptions
():
Promise
<
FormattingOptions
>
{
if
(
!
this
.
_formattingOptions
)
{
this
.
_formattingOptions
=
this
.
userDataSyncUtilService
.
resolveFormattingOptions
(
this
.
file
);
}
return
this
.
_formattingOptions
;
}
}
src/vs/platform/userDataSync/common/extensionsSync.ts
浏览文件 @
d022bb76
...
...
@@ -33,7 +33,8 @@ interface ILastSyncUserData extends IUserData {
export
class
ExtensionsSynchroniser
extends
AbstractSynchroniser
implements
IUserDataSynchroniser
{
protected
get
enabled
():
boolean
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
sync.enableExtensions
'
)
===
true
;
}
protected
get
remoteDataResourceKey
():
string
{
return
'
extensions
'
;
}
protected
get
enabled
():
boolean
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
sync.enableExtensions
'
)
===
true
&&
this
.
extensionGalleryService
.
isEnabled
();
}
constructor
(
@
IEnvironmentService
environmentService
:
IEnvironmentService
,
...
...
@@ -41,12 +42,12 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
@
IUserDataSyncStoreService
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
IExtensionManagementService
private
readonly
extensionManagementService
:
IExtensionManagementService
,
@
IGlobalExtensionEnablementService
private
readonly
extensionEnablementService
:
IGlobalExtensionEnablementService
,
@
IUserDataSyncLogService
private
readonly
logService
:
IUserDataSyncLogService
,
@
IUserDataSyncLogService
logService
:
IUserDataSyncLogService
,
@
IExtensionGalleryService
private
readonly
extensionGalleryService
:
IExtensionGalleryService
,
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
)
{
super
(
SyncSource
.
Extensions
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
);
super
(
SyncSource
.
Extensions
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
,
logService
);
this
.
_register
(
Event
.
debounce
(
Event
.
any
<
any
>
(
...
...
@@ -56,8 +57,6 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
()
=>
undefined
,
500
)(()
=>
this
.
_onDidChangeLocal
.
fire
()));
}
protected
getRemoteDataResourceKey
():
string
{
return
'
extensions
'
;
}
async
pull
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
'
Extensions: Skipped pulling extensions as it is disabled.
'
);
...
...
@@ -117,37 +116,11 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
}
async
sync
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
'
Extensions: Skipping synchronizing extensions as it is disabled.
'
);
return
;
}
if
(
!
this
.
extensionGalleryService
.
isEnabled
())
{
this
.
logService
.
info
(
'
Extensions: Skipping synchronizing extensions as gallery is disabled.
'
);
return
;
}
if
(
this
.
status
!==
SyncStatus
.
Idle
)
{
this
.
logService
.
info
(
'
Extensions: Skipping synchronizing extensions as it is running already.
'
);
return
;
}
this
.
logService
.
trace
(
'
Extensions: Started synchronizing extensions...
'
);
this
.
setStatus
(
SyncStatus
.
Syncing
);
try
{
const
previewResult
=
await
this
.
getPreview
();
await
this
.
apply
(
previewResult
);
}
catch
(
e
)
{
this
.
setStatus
(
SyncStatus
.
Idle
);
if
(
e
instanceof
UserDataSyncError
&&
e
.
code
===
UserDataSyncErrorCode
.
Rejected
)
{
// Rejected as there is a new remote version. Syncing again,
this
.
logService
.
info
(
'
Extensions: Failed to synchronize extensions as there is a new remote version available. Synchronizing again...
'
);
return
this
.
sync
();
}
throw
e
;
}
this
.
logService
.
trace
(
'
Extensions: Finished synchronizing extensions.
'
);
this
.
setStatus
(
SyncStatus
.
Idle
);
return
super
.
sync
();
}
async
stop
():
Promise
<
void
>
{
}
...
...
@@ -172,6 +145,24 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
return
null
;
}
protected
async
doSync
():
Promise
<
void
>
{
try
{
const
previewResult
=
await
this
.
getPreview
();
await
this
.
apply
(
previewResult
);
}
catch
(
e
)
{
this
.
setStatus
(
SyncStatus
.
Idle
);
if
(
e
instanceof
UserDataSyncError
&&
e
.
code
===
UserDataSyncErrorCode
.
Rejected
)
{
// Rejected as there is a new remote version. Syncing again,
this
.
logService
.
info
(
'
Extensions: Failed to synchronize extensions as there is a new remote version available. Synchronizing again...
'
);
return
this
.
sync
();
}
throw
e
;
}
this
.
logService
.
trace
(
'
Extensions: Finished synchronizing extensions.
'
);
this
.
setStatus
(
SyncStatus
.
Idle
);
}
private
async
getPreview
():
Promise
<
ISyncPreviewResult
>
{
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
<
ILastSyncUserData
>
();
const
lastSyncExtensions
:
ISyncExtension
[]
|
null
=
lastSyncUserData
?
JSON
.
parse
(
lastSyncUserData
.
content
!
)
:
null
;
...
...
src/vs/platform/userDataSync/common/globalStateSync.ts
浏览文件 @
d022bb76
...
...
@@ -28,23 +28,22 @@ interface ISyncPreviewResult {
export
class
GlobalStateSynchroniser
extends
AbstractSynchroniser
implements
IUserDataSynchroniser
{
protected
get
remoteDataResourceKey
():
string
{
return
'
globalState
'
;
}
protected
get
enabled
():
boolean
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
sync.enableUIState
'
)
===
true
;
}
constructor
(
@
IFileService
fileService
:
IFileService
,
@
IUserDataSyncStoreService
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
IUserDataSyncLogService
private
readonly
logService
:
IUserDataSyncLogService
,
@
IUserDataSyncLogService
logService
:
IUserDataSyncLogService
,
@
IEnvironmentService
private
readonly
environmentService
:
IEnvironmentService
,
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
)
{
super
(
SyncSource
.
GlobalState
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
);
super
(
SyncSource
.
GlobalState
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
,
logService
);
this
.
_register
(
this
.
fileService
.
watch
(
dirname
(
this
.
environmentService
.
argvResource
)));
this
.
_register
(
Event
.
filter
(
this
.
fileService
.
onFileChanges
,
e
=>
e
.
contains
(
this
.
environmentService
.
argvResource
))(()
=>
this
.
_onDidChangeLocal
.
fire
()));
}
protected
getRemoteDataResourceKey
():
string
{
return
'
globalState
'
;
}
async
pull
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
'
UI State: Skipped pulling ui state as it is disabled.
'
);
...
...
@@ -100,36 +99,6 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
}
async
sync
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
'
UI State: Skipping synchronizing UI state as it is disabled.
'
);
return
;
}
if
(
this
.
status
!==
SyncStatus
.
Idle
)
{
this
.
logService
.
info
(
'
UI State: Skipping synchronizing ui state as it is running already.
'
);
return
;
}
this
.
logService
.
trace
(
'
UI State: Started synchronizing ui state...
'
);
this
.
setStatus
(
SyncStatus
.
Syncing
);
try
{
const
result
=
await
this
.
getPreview
();
await
this
.
apply
(
result
);
this
.
logService
.
trace
(
'
UI State: Finished synchronizing ui state.
'
);
}
catch
(
e
)
{
this
.
setStatus
(
SyncStatus
.
Idle
);
if
(
e
instanceof
UserDataSyncError
&&
e
.
code
===
UserDataSyncErrorCode
.
Rejected
)
{
// Rejected as there is a new remote version. Syncing again,
this
.
logService
.
info
(
'
UI State: Failed to synchronize ui state as there is a new remote version available. Synchronizing again...
'
);
return
this
.
sync
();
}
throw
e
;
}
finally
{
this
.
setStatus
(
SyncStatus
.
Idle
);
}
}
async
stop
():
Promise
<
void
>
{
}
accept
(
content
:
string
):
Promise
<
void
>
{
...
...
@@ -152,6 +121,24 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
return
null
;
}
protected
async
doSync
():
Promise
<
void
>
{
try
{
const
result
=
await
this
.
getPreview
();
await
this
.
apply
(
result
);
this
.
logService
.
trace
(
'
UI State: Finished synchronizing ui state.
'
);
}
catch
(
e
)
{
this
.
setStatus
(
SyncStatus
.
Idle
);
if
(
e
instanceof
UserDataSyncError
&&
e
.
code
===
UserDataSyncErrorCode
.
Rejected
)
{
// Rejected as there is a new remote version. Syncing again,
this
.
logService
.
info
(
'
UI State: Failed to synchronize ui state as there is a new remote version available. Synchronizing again...
'
);
return
this
.
sync
();
}
throw
e
;
}
finally
{
this
.
setStatus
(
SyncStatus
.
Idle
);
}
}
private
async
getPreview
():
Promise
<
ISyncPreviewResult
>
{
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
lastSyncGlobalState
=
lastSyncUserData
&&
lastSyncUserData
.
content
?
JSON
.
parse
(
lastSyncUserData
.
content
)
:
null
;
...
...
src/vs/platform/userDataSync/common/keybindingsSync.ts
浏览文件 @
d022bb76
...
...
@@ -3,22 +3,22 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IFileService
,
IFileContent
,
FileOperationError
,
FileOperationResult
}
from
'
vs/platform/files/common/files
'
;
import
{
IUserData
,
UserDataSyncError
,
UserDataSyncErrorCode
,
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
SyncSource
,
IUserDataSynchroniser
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IFileService
,
FileOperationError
,
FileOperationResult
}
from
'
vs/platform/files/common/files
'
;
import
{
UserDataSyncError
,
UserDataSyncErrorCode
,
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
SyncSource
,
IUserDataSynchroniser
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
merge
}
from
'
vs/platform/userDataSync/common/keybindingsMerge
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
parse
,
ParseError
}
from
'
vs/base/common/json
'
;
import
{
parse
}
from
'
vs/base/common/json
'
;
import
{
localize
}
from
'
vs/nls
'
;
import
{
CancelablePromise
,
createCancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
createCancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
OS
,
OperatingSystem
}
from
'
vs/base/common/platform
'
;
import
{
isUndefined
}
from
'
vs/base/common/types
'
;
import
{
FormattingOptions
}
from
'
vs/base/common/jsonFormatter
'
;
import
{
isNonEmptyArray
}
from
'
vs/base/common/arrays
'
;
import
{
Abstract
FileSynchroniser
}
from
'
vs/platform/userDataSync/common/abstractSynchronizer
'
;
import
{
IFileSyncPreviewResult
,
AbstractJson
FileSynchroniser
}
from
'
vs/platform/userDataSync/common/abstractSynchronizer
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
interface
ISyncContent
{
mac
?:
string
;
...
...
@@ -27,40 +27,22 @@ interface ISyncContent {
all
?:
string
;
}
interface
ISyncPreviewResult
{
readonly
fileContent
:
IFileContent
|
null
;
readonly
remoteUserData
:
IUserData
;
readonly
lastSyncUserData
:
IUserData
|
null
;
readonly
content
:
string
|
null
;
readonly
hasLocalChanged
:
boolean
;
readonly
hasRemoteChanged
:
boolean
;
readonly
hasConflicts
:
boolean
;
}
export
class
KeybindingsSynchroniser
extends
AbstractFileSynchroniser
implements
IUserDataSynchroniser
{
export
class
KeybindingsSynchroniser
extends
AbstractJsonFileSynchroniser
implements
IUserDataSynchroniser
{
private
syncPreviewResultPromise
:
CancelablePromise
<
ISyncPreviewResult
>
|
null
=
null
;
protected
get
remoteDataResourceKey
():
string
{
return
'
keybindings
'
;
}
protected
get
conflictsPreviewResource
():
URI
{
return
this
.
environmentService
.
keybindingsSyncPreviewResource
;
}
protected
get
enabled
():
boolean
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
sync.enableKeybindings
'
)
===
true
;
}
constructor
(
@
IUserDataSyncStoreService
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
IUserDataSyncLogService
private
readonly
logService
:
IUserDataSyncLogService
,
@
IUserDataSyncLogService
logService
:
IUserDataSyncLogService
,
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
IFileService
fileService
:
IFileService
,
@
IEnvironmentService
private
readonly
environmentService
:
IEnvironmentService
,
@
IUserDataSyncUtilService
private
readonly
userDataSyncUtilService
:
IUserDataSyncUtilService
,
@
IUserDataSyncUtilService
userDataSyncUtilService
:
IUserDataSyncUtilService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
)
{
super
(
environmentService
.
keybindingsResource
,
SyncSource
.
Keybindings
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
);
}
protected
getRemoteDataResourceKey
():
string
{
return
'
keybindings
'
;
}
protected
cancel
():
void
{
if
(
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
.
cancel
();
this
.
syncPreviewResultPromise
=
null
;
}
super
(
environmentService
.
keybindingsResource
,
SyncSource
.
Keybindings
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
,
logService
,
userDataSyncUtilService
);
}
async
pull
():
Promise
<
void
>
{
...
...
@@ -81,7 +63,7 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements
if
(
content
!==
null
)
{
const
fileContent
=
await
this
.
getLocalFileContent
();
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISyncPreviewResult
>
({
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
I
File
SyncPreviewResult
>
({
fileContent
,
remoteUserData
,
lastSyncUserData
,
...
...
@@ -122,7 +104,7 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements
if
(
fileContent
!==
null
)
{
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISyncPreviewResult
>
({
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
I
File
SyncPreviewResult
>
({
fileContent
,
remoteUserData
,
lastSyncUserData
,
...
...
@@ -146,28 +128,6 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements
}
async
sync
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
'
Keybindings: Skipping synchronizing keybindings as it is disabled.
'
);
return
;
}
if
(
this
.
status
!==
SyncStatus
.
Idle
)
{
this
.
logService
.
info
(
'
Keybindings: Skipping synchronizing keybindings as it is running already.
'
);
return
;
}
this
.
logService
.
trace
(
'
Keybindings: Started synchronizing keybindings...
'
);
this
.
setStatus
(
SyncStatus
.
Syncing
);
return
this
.
doSync
();
}
async
stop
():
Promise
<
void
>
{
this
.
cancel
();
this
.
logService
.
trace
(
'
Keybindings: Stopped synchronizing keybindings.
'
);
await
this
.
fileService
.
del
(
this
.
environmentService
.
keybindingsSyncPreviewResource
);
this
.
setStatus
(
SyncStatus
.
Idle
);
}
async
accept
(
content
:
string
):
Promise
<
void
>
{
if
(
this
.
status
===
SyncStatus
.
HasConflicts
)
{
const
preview
=
await
this
.
syncPreviewResultPromise
!
;
...
...
@@ -195,17 +155,9 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements
return
false
;
}
async
getRemoteContent
():
Promise
<
string
|
null
>
{
let
content
:
string
|
null
|
undefined
=
null
;
if
(
this
.
syncPreviewResultPromise
)
{
const
preview
=
await
this
.
syncPreviewResultPromise
;
content
=
preview
.
remoteUserData
?.
content
;
}
else
{
const
lastSyncData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncData
);
content
=
remoteUserData
.
content
;
}
return
content
?
this
.
getKeybindingsContentFromSyncContent
(
content
)
:
null
;
async
getRemoteContent
(
preview
?:
boolean
):
Promise
<
string
|
null
>
{
const
content
=
await
super
.
getRemoteContent
(
preview
);
return
content
!==
null
?
this
.
getKeybindingsContentFromSyncContent
(
content
)
:
null
;
}
protected
async
doSync
():
Promise
<
void
>
{
...
...
@@ -285,20 +237,14 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements
this
.
syncPreviewResultPromise
=
null
;
}
private
hasErrors
(
content
:
string
):
boolean
{
const
parseErrors
:
ParseError
[]
=
[];
parse
(
content
,
parseErrors
,
{
allowEmptyContent
:
true
,
allowTrailingComma
:
true
});
return
parseErrors
.
length
>
0
;
}
private
getPreview
():
Promise
<
ISyncPreviewResult
>
{
private
getPreview
():
Promise
<
IFileSyncPreviewResult
>
{
if
(
!
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
=
createCancelablePromise
(
token
=>
this
.
generatePreview
(
token
));
}
return
this
.
syncPreviewResultPromise
;
}
private
async
generatePreview
(
token
:
CancellationToken
):
Promise
<
ISyncPreviewResult
>
{
private
async
generatePreview
(
token
:
CancellationToken
):
Promise
<
I
File
SyncPreviewResult
>
{
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
lastSyncContent
=
lastSyncUserData
&&
lastSyncUserData
.
content
?
this
.
getKeybindingsContentFromSyncContent
(
lastSyncUserData
.
content
)
:
null
;
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
...
...
@@ -349,14 +295,6 @@ export class KeybindingsSynchroniser extends AbstractFileSynchroniser implements
return
{
fileContent
,
remoteUserData
,
lastSyncUserData
,
content
,
hasLocalChanged
,
hasRemoteChanged
,
hasConflicts
};
}
private
_formattingOptions
:
Promise
<
FormattingOptions
>
|
undefined
=
undefined
;
private
getFormattingOptions
():
Promise
<
FormattingOptions
>
{
if
(
!
this
.
_formattingOptions
)
{
this
.
_formattingOptions
=
this
.
userDataSyncUtilService
.
resolveFormattingOptions
(
this
.
environmentService
.
keybindingsResource
);
}
return
this
.
_formattingOptions
;
}
private
getKeybindingsContentFromSyncContent
(
syncContent
:
string
):
string
|
null
{
try
{
const
parsed
=
<
ISyncContent
>
JSON
.
parse
(
syncContent
);
...
...
src/vs/platform/userDataSync/common/settingsSync.ts
浏览文件 @
d022bb76
...
...
@@ -3,63 +3,50 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IFileService
,
IFileContent
,
FileOperationError
,
FileOperationResult
}
from
'
vs/platform/files/common/files
'
;
import
{
IUserData
,
UserDataSyncError
,
UserDataSyncErrorCode
,
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
IConflictSetting
,
ISettingsSyncService
,
CONFIGURATION_SYNC_STORE_KEY
,
SyncSource
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IFileService
,
FileOperationError
,
FileOperationResult
}
from
'
vs/platform/files/common/files
'
;
import
{
UserDataSyncError
,
UserDataSyncErrorCode
,
SyncStatus
,
IUserDataSyncStoreService
,
IUserDataSyncLogService
,
IUserDataSyncUtilService
,
IConflictSetting
,
ISettingsSyncService
,
CONFIGURATION_SYNC_STORE_KEY
,
SyncSource
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
parse
,
ParseError
}
from
'
vs/base/common/json
'
;
import
{
parse
}
from
'
vs/base/common/json
'
;
import
{
localize
}
from
'
vs/nls
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
CancelablePromise
,
createCancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
createCancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
updateIgnoredSettings
,
merge
,
getIgnoredSettings
}
from
'
vs/platform/userDataSync/common/settingsMerge
'
;
import
{
FormattingOptions
}
from
'
vs/base/common/jsonFormatter
'
;
import
*
as
arrays
from
'
vs/base/common/arrays
'
;
import
*
as
objects
from
'
vs/base/common/objects
'
;
import
{
isEmptyObject
,
isUndefinedOrNull
}
from
'
vs/base/common/types
'
;
import
{
isEmptyObject
}
from
'
vs/base/common/types
'
;
import
{
edit
}
from
'
vs/platform/userDataSync/common/content
'
;
import
{
Abstract
FileSynchroniser
}
from
'
vs/platform/userDataSync/common/abstractSynchronizer
'
;
import
{
IFileSyncPreviewResult
,
AbstractJson
FileSynchroniser
}
from
'
vs/platform/userDataSync/common/abstractSynchronizer
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
interface
ISyncPreviewResult
{
readonly
fileContent
:
IFileContent
|
null
;
readonly
remoteUserData
:
IUserData
;
readonly
lastSyncUserData
:
IUserData
|
null
;
readonly
content
:
string
|
null
;
readonly
hasLocalChanged
:
boolean
;
readonly
hasRemoteChanged
:
boolean
;
readonly
hasConflicts
:
boolean
;
readonly
conflictSettings
:
IConflictSetting
[];
}
export
class
SettingsSynchroniser
extends
AbstractFileSynchroniser
implements
ISettingsSyncService
{
export
class
SettingsSynchroniser
extends
AbstractJsonFileSynchroniser
implements
ISettingsSyncService
{
_serviceBrand
:
any
;
private
syncPreviewResultPromise
:
CancelablePromise
<
ISyncPreviewResult
>
|
null
=
null
;
protected
get
remoteDataResourceKey
():
string
{
return
'
settings
'
;
}
protected
get
conflictsPreviewResource
():
URI
{
return
this
.
environmentService
.
settingsSyncPreviewResource
;
}
protected
get
enabled
():
boolean
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
sync.enableSettings
'
)
===
true
;
}
private
_conflicts
:
IConflictSetting
[]
=
[];
get
conflicts
():
IConflictSetting
[]
{
return
this
.
_conflicts
;
}
private
_onDidChangeConflicts
:
Emitter
<
IConflictSetting
[]
>
=
this
.
_register
(
new
Emitter
<
IConflictSetting
[]
>
());
readonly
onDidChangeConflicts
:
Event
<
IConflictSetting
[]
>
=
this
.
_onDidChangeConflicts
.
event
;
protected
get
enabled
():
boolean
{
return
this
.
configurationService
.
getValue
<
boolean
>
(
'
sync.enableSettings
'
)
===
true
;
}
constructor
(
@
IFileService
fileService
:
IFileService
,
@
IEnvironmentService
private
readonly
environmentService
:
IEnvironmentService
,
@
IUserDataSyncStoreService
userDataSyncStoreService
:
IUserDataSyncStoreService
,
@
IUserDataSyncLogService
private
readonly
logService
:
IUserDataSyncLogService
,
@
IUserDataSyncUtilService
private
readonly
userDataSyncUtilService
:
IUserDataSyncUtilService
,
@
IUserDataSyncLogService
logService
:
IUserDataSyncLogService
,
@
IUserDataSyncUtilService
userDataSyncUtilService
:
IUserDataSyncUtilService
,
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
)
{
super
(
environmentService
.
settingsResource
,
SyncSource
.
Settings
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
);
super
(
environmentService
.
settingsResource
,
SyncSource
.
Settings
,
fileService
,
environmentService
,
userDataSyncStoreService
,
telemetryService
,
logService
,
userDataSyncUtilService
);
}
protected
getRemoteDataResourceKey
():
string
{
return
'
settings
'
;
}
protected
setStatus
(
status
:
SyncStatus
):
void
{
super
.
setStatus
(
status
);
if
(
this
.
status
!==
SyncStatus
.
HasConflicts
)
{
...
...
@@ -67,13 +54,6 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
}
}
protected
cancel
():
void
{
if
(
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
.
cancel
();
this
.
syncPreviewResultPromise
=
null
;
}
}
private
setConflicts
(
conflicts
:
IConflictSetting
[]):
void
{
if
(
!
arrays
.
equals
(
this
.
conflicts
,
conflicts
,
(
a
,
b
)
=>
a
.
key
===
b
.
key
&&
objects
.
equals
(
a
.
localValue
,
b
.
localValue
)
&&
objects
.
equals
(
a
.
remoteValue
,
b
.
remoteValue
))
...
...
@@ -103,7 +83,7 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
const
formatUtils
=
await
this
.
getFormattingOptions
();
// Update ignored settings from local file content
const
content
=
updateIgnoredSettings
(
remoteUserData
.
content
,
fileContent
?
fileContent
.
value
.
toString
()
:
'
{}
'
,
getIgnoredSettings
(
this
.
configurationService
),
formatUtils
);
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISyncPreviewResult
>
({
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
I
File
SyncPreviewResult
>
({
fileContent
,
remoteUserData
,
lastSyncUserData
,
...
...
@@ -111,7 +91,6 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
hasLocalChanged
:
true
,
hasRemoteChanged
:
false
,
hasConflicts
:
false
,
conflictSettings
:
[],
}));
await
this
.
apply
();
...
...
@@ -149,7 +128,7 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
ISyncPreviewResult
>
({
this
.
syncPreviewResultPromise
=
createCancelablePromise
(()
=>
Promise
.
resolve
<
I
File
SyncPreviewResult
>
({
fileContent
,
remoteUserData
,
lastSyncUserData
,
...
...
@@ -157,7 +136,6 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
hasRemoteChanged
:
true
,
hasLocalChanged
:
false
,
hasConflicts
:
false
,
conflictSettings
:
[],
}));
await
this
.
apply
(
true
);
...
...
@@ -174,28 +152,6 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
}
}
async
sync
():
Promise
<
void
>
{
if
(
!
this
.
enabled
)
{
this
.
logService
.
info
(
'
Settings: Skipping synchronizing settings as it is disabled.
'
);
return
;
}
if
(
this
.
status
!==
SyncStatus
.
Idle
)
{
this
.
logService
.
info
(
'
Settings: Skipping synchronizing settings as it is running already.
'
);
return
;
}
this
.
logService
.
trace
(
'
Settings: Started synchronizing settings...
'
);
this
.
setStatus
(
SyncStatus
.
Syncing
);
return
this
.
doSync
([]);
}
async
stop
():
Promise
<
void
>
{
this
.
cancel
();
this
.
logService
.
trace
(
'
Settings: Stopped synchronizing settings.
'
);
await
this
.
fileService
.
del
(
this
.
environmentService
.
settingsSyncPreviewResource
);
this
.
setStatus
(
SyncStatus
.
Idle
);
}
async
hasLocalData
():
Promise
<
boolean
>
{
try
{
const
localFileContent
=
await
this
.
getLocalFileContent
();
...
...
@@ -216,21 +172,13 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
}
async
getRemoteContent
(
preview
?:
boolean
):
Promise
<
string
|
null
>
{
let
content
:
string
|
null
|
undefined
=
null
;
if
(
this
.
syncPreviewResultPromise
)
{
const
preview
=
await
this
.
syncPreviewResultPromise
;
content
=
preview
.
remoteUserData
?.
content
;
}
else
{
const
lastSyncData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncData
);
content
=
remoteUserData
.
content
;
}
if
(
preview
&&
!
isUndefinedOrNull
(
content
))
{
let
content
=
await
super
.
getRemoteContent
(
preview
);
if
(
preview
&&
content
!==
null
)
{
const
formatUtils
=
await
this
.
getFormattingOptions
();
// remove ignored settings from the remote content for preview
content
=
updateIgnoredSettings
(
content
,
'
{}
'
,
getIgnoredSettings
(
this
.
configurationService
),
formatUtils
);
}
return
content
!==
undefined
?
content
:
null
;
return
content
;
}
async
accept
(
content
:
string
):
Promise
<
void
>
{
...
...
@@ -331,20 +279,14 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
this
.
syncPreviewResultPromise
=
null
;
}
private
hasErrors
(
content
:
string
):
boolean
{
const
parseErrors
:
ParseError
[]
=
[];
parse
(
content
,
parseErrors
,
{
allowEmptyContent
:
true
,
allowTrailingComma
:
true
});
return
parseErrors
.
length
>
0
;
}
private
getPreview
(
resolvedConflicts
:
{
key
:
string
,
value
:
any
}[]):
Promise
<
ISyncPreviewResult
>
{
private
getPreview
(
resolvedConflicts
:
{
key
:
string
,
value
:
any
}[]):
Promise
<
IFileSyncPreviewResult
>
{
if
(
!
this
.
syncPreviewResultPromise
)
{
this
.
syncPreviewResultPromise
=
createCancelablePromise
(
token
=>
this
.
generatePreview
(
resolvedConflicts
,
token
));
}
return
this
.
syncPreviewResultPromise
;
}
pr
ivate
async
generatePreview
(
resolvedConflicts
:
{
key
:
string
,
value
:
any
}[],
token
:
CancellationToken
):
Promise
<
I
SyncPreviewResult
>
{
pr
otected
async
generatePreview
(
resolvedConflicts
:
{
key
:
string
,
value
:
any
}[],
token
:
CancellationToken
):
Promise
<
IFile
SyncPreviewResult
>
{
const
lastSyncUserData
=
await
this
.
getLastSyncUserData
();
const
remoteUserData
=
await
this
.
getRemoteUserData
(
lastSyncUserData
);
// Get file content last to get the latest
...
...
@@ -390,15 +332,7 @@ export class SettingsSynchroniser extends AbstractFileSynchroniser implements IS
}
this
.
setConflicts
(
conflictSettings
);
return
{
fileContent
,
remoteUserData
,
lastSyncUserData
,
content
,
hasLocalChanged
,
hasRemoteChanged
,
conflictSettings
,
hasConflicts
};
}
private
_formattingOptions
:
Promise
<
FormattingOptions
>
|
undefined
=
undefined
;
private
getFormattingOptions
():
Promise
<
FormattingOptions
>
{
if
(
!
this
.
_formattingOptions
)
{
this
.
_formattingOptions
=
this
.
userDataSyncUtilService
.
resolveFormattingOptions
(
this
.
environmentService
.
settingsResource
);
}
return
this
.
_formattingOptions
;
return
{
fileContent
,
remoteUserData
,
lastSyncUserData
,
content
,
hasLocalChanged
,
hasRemoteChanged
,
hasConflicts
};
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录