Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
240d1b73
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,发现更多精彩内容 >>
提交
240d1b73
编写于
5月 25, 2020
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix #98513
上级
1fd39577
变更
4
展开全部
隐藏空白更改
内联
并排
Showing
4 changed file
with
433 addition
and
282 deletion
+433
-282
src/vs/platform/userDataSync/common/extensionsMerge.ts
src/vs/platform/userDataSync/common/extensionsMerge.ts
+95
-71
src/vs/platform/userDataSync/common/extensionsSync.ts
src/vs/platform/userDataSync/common/extensionsSync.ts
+37
-15
src/vs/platform/userDataSync/common/userDataSync.ts
src/vs/platform/userDataSync/common/userDataSync.ts
+1
-0
src/vs/platform/userDataSync/test/common/extensionsMerge.test.ts
...platform/userDataSync/test/common/extensionsMerge.test.ts
+300
-196
未找到文件。
src/vs/platform/userDataSync/common/extensionsMerge.ts
浏览文件 @
240d1b73
...
...
@@ -7,6 +7,7 @@ import { values, keys } from 'vs/base/common/map';
import
{
ISyncExtension
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IExtensionIdentifier
}
from
'
vs/platform/extensions/common/extensions
'
;
import
{
startsWith
}
from
'
vs/base/common/strings
'
;
import
{
deepClone
}
from
'
vs/base/common/objects
'
;
export
interface
IMergeResult
{
added
:
ISyncExtension
[];
...
...
@@ -30,8 +31,6 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
};
}
// massage incoming extension - add disabled property
const
massageIncomingExtension
=
(
extension
:
ISyncExtension
):
ISyncExtension
=>
({
...
extension
,
...{
disabled
:
!!
extension
.
disabled
}
});
localExtensions
=
localExtensions
.
map
(
massageIncomingExtension
);
remoteExtensions
=
remoteExtensions
.
map
(
massageIncomingExtension
);
lastSyncExtensions
=
lastSyncExtensions
?
lastSyncExtensions
.
map
(
massageIncomingExtension
)
:
null
;
...
...
@@ -54,7 +53,14 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
};
const
localExtensionsMap
=
localExtensions
.
reduce
(
addExtensionToMap
,
new
Map
<
string
,
ISyncExtension
>
());
const
remoteExtensionsMap
=
remoteExtensions
.
reduce
(
addExtensionToMap
,
new
Map
<
string
,
ISyncExtension
>
());
const
newRemoteExtensionsMap
=
remoteExtensions
.
reduce
(
addExtensionToMap
,
new
Map
<
string
,
ISyncExtension
>
());
const
newRemoteExtensionsMap
=
remoteExtensions
.
reduce
((
map
:
Map
<
string
,
ISyncExtension
>
,
extension
:
ISyncExtension
)
=>
{
const
key
=
getKey
(
extension
);
extension
=
deepClone
(
extension
);
if
(
localExtensionsMap
.
get
(
key
)?.
installed
)
{
extension
.
installed
=
true
;
}
return
addExtensionToMap
(
map
,
extension
);
},
new
Map
<
string
,
ISyncExtension
>
());
const
lastSyncExtensionsMap
=
lastSyncExtensions
?
lastSyncExtensions
.
reduce
(
addExtensionToMap
,
new
Map
<
string
,
ISyncExtension
>
())
:
null
;
const
skippedExtensionsMap
=
skippedExtensions
.
reduce
(
addExtensionToMap
,
new
Map
<
string
,
ISyncExtension
>
());
const
ignoredExtensionsSet
=
ignoredExtensions
.
reduce
((
set
,
id
)
=>
{
...
...
@@ -63,90 +69,82 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
},
new
Set
<
string
>
());
const
localToRemote
=
compare
(
localExtensionsMap
,
remoteExtensionsMap
,
ignoredExtensionsSet
);
if
(
localToRemote
.
added
.
size
===
0
&&
localToRemote
.
removed
.
size
===
0
&&
localToRemote
.
updated
.
size
===
0
)
{
// No changes found between local and remote.
return
{
added
:
[],
removed
:
[],
updated
:
[],
remote
:
null
};
}
if
(
localToRemote
.
added
.
size
>
0
||
localToRemote
.
removed
.
size
>
0
||
localToRemote
.
updated
.
size
>
0
)
{
const
baseToLocal
=
compare
(
lastSyncExtensionsMap
,
localExtensionsMap
,
ignoredExtensionsSet
);
const
baseToRemote
=
compare
(
lastSyncExtensionsMap
,
remoteExtensionsMap
,
ignoredExtensionsSet
);
// massage outgoing extension - remove disabled property
const
massageOutgoingExtension
=
(
extension
:
ISyncExtension
,
key
:
string
):
ISyncExtension
=>
{
const
massagedExtension
:
ISyncExtension
=
{
identifier
:
{
id
:
extension
.
identifier
.
id
,
uuid
:
startsWith
(
key
,
'
uuid:
'
)
?
key
.
substring
(
'
uuid:
'
.
length
)
:
undefined
},
};
if
(
extension
.
disabled
)
{
massagedExtension
.
disabled
=
true
;
}
if
(
extension
.
version
)
{
massagedExtension
.
version
=
extension
.
version
;
}
return
massagedExtension
;
};
const
baseToLocal
=
compare
(
lastSyncExtensionsMap
,
localExtensionsMap
,
ignoredExtensionsSet
);
const
baseToRemote
=
compare
(
lastSyncExtensionsMap
,
remoteExtensionsMap
,
ignoredExtensionsSet
);
// Remotely removed extension.
for
(
const
key
of
values
(
baseToRemote
.
removed
))
{
const
e
=
localExtensionsMap
.
get
(
key
);
if
(
e
)
{
removed
.
push
(
e
.
identifier
);
// Remotely removed extension.
for
(
const
key
of
values
(
baseToRemote
.
removed
))
{
const
e
=
localExtensionsMap
.
get
(
key
);
if
(
e
)
{
removed
.
push
(
e
.
identifier
);
}
}
}
// Remotely added extension
for
(
const
key
of
values
(
baseToRemote
.
added
))
{
// Got added in local
if
(
baseToLocal
.
added
.
has
(
key
))
{
// Is different from local to remote
if
(
localToRemote
.
updated
.
has
(
key
))
{
updated
.
push
(
massageOutgoingExtension
(
remoteExtensionsMap
.
get
(
key
)
!
,
key
));
// Remotely added extension
for
(
const
key
of
values
(
baseToRemote
.
added
))
{
// Got added in local
if
(
baseToLocal
.
added
.
has
(
key
))
{
// Is different from local to remote
if
(
localToRemote
.
updated
.
has
(
key
))
{
updated
.
push
(
massageOutgoingExtension
(
remoteExtensionsMap
.
get
(
key
)
!
,
key
));
}
}
else
{
// Add only installed extension to local
const
remoteExtension
=
remoteExtensionsMap
.
get
(
key
)
!
;
if
(
remoteExtension
.
installed
)
{
added
.
push
(
massageOutgoingExtension
(
remoteExtension
,
key
));
}
}
}
else
{
// Add to local
added
.
push
(
massageOutgoingExtension
(
remoteExtensionsMap
.
get
(
key
)
!
,
key
));
}
}
// Remotely updated extensions
for
(
const
key
of
values
(
baseToRemote
.
updated
))
{
// Update in local always
updated
.
push
(
massageOutgoingExtension
(
remoteExtensionsMap
.
get
(
key
)
!
,
key
));
}
// Locally added extensions
for
(
const
key
of
values
(
baseToLocal
.
added
))
{
// Not there in remote
if
(
!
baseToRemote
.
added
.
has
(
key
))
{
newRemoteExtensionsMap
.
set
(
key
,
localExtensionsMap
.
get
(
key
)
!
);
// Remotely updated extensions
for
(
const
key
of
values
(
baseToRemote
.
updated
))
{
// Update in local always
updated
.
push
(
massageOutgoingExtension
(
remoteExtensionsMap
.
get
(
key
)
!
,
key
));
}
}
// Locally updated extensions
for
(
const
key
of
values
(
baseToLocal
.
updated
))
{
// If removed in remote
if
(
baseToRemote
.
removed
.
has
(
key
))
{
continue
;
// Locally added extensions
for
(
const
key
of
values
(
baseToLocal
.
added
))
{
// Not there in remote
if
(
!
baseToRemote
.
added
.
has
(
key
))
{
newRemoteExtensionsMap
.
set
(
key
,
localExtensionsMap
.
get
(
key
)
!
);
}
}
// If not updated in remote
if
(
!
baseToRemote
.
updated
.
has
(
key
))
{
newRemoteExtensionsMap
.
set
(
key
,
localExtensionsMap
.
get
(
key
)
!
);
// Locally updated extensions
for
(
const
key
of
values
(
baseToLocal
.
updated
))
{
// If removed in remote
if
(
baseToRemote
.
removed
.
has
(
key
))
{
continue
;
}
// If not updated in remote
if
(
!
baseToRemote
.
updated
.
has
(
key
))
{
const
extension
=
deepClone
(
localExtensionsMap
.
get
(
key
)
!
);
// Retain installed property
if
(
newRemoteExtensionsMap
.
get
(
key
)?.
installed
)
{
extension
.
installed
=
true
;
}
newRemoteExtensionsMap
.
set
(
key
,
extension
);
}
}
}
// Locally removed extensions
for
(
const
key
of
values
(
baseToLocal
.
removed
))
{
// If not skipped and not updated in remote
if
(
!
skippedExtensionsMap
.
has
(
key
)
&&
!
baseToRemote
.
updated
.
has
(
key
))
{
newRemoteExtensionsMap
.
delete
(
key
);
// Locally removed extensions
for
(
const
key
of
values
(
baseToLocal
.
removed
))
{
// If not skipped and not updated in remote
if
(
!
skippedExtensionsMap
.
has
(
key
)
&&
!
baseToRemote
.
updated
.
has
(
key
))
{
// Remove only if it is an installed extension
if
(
lastSyncExtensionsMap
?.
get
(
key
)?.
installed
)
{
newRemoteExtensionsMap
.
delete
(
key
);
}
}
}
}
const
remote
:
ISyncExtension
[]
=
[];
const
remoteChanges
=
compare
(
remoteExtensionsMap
,
newRemoteExtensionsMap
,
new
Set
<
string
>
());
const
remoteChanges
=
compare
(
remoteExtensionsMap
,
newRemoteExtensionsMap
,
new
Set
<
string
>
()
,
{
checkInstalledProperty
:
true
}
);
if
(
remoteChanges
.
added
.
size
>
0
||
remoteChanges
.
updated
.
size
>
0
||
remoteChanges
.
removed
.
size
>
0
)
{
newRemoteExtensionsMap
.
forEach
((
value
,
key
)
=>
remote
.
push
(
massageOutgoingExtension
(
value
,
key
)));
}
...
...
@@ -154,7 +152,7 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
return
{
added
,
removed
,
updated
,
remote
:
remote
.
length
?
remote
:
null
};
}
function
compare
(
from
:
Map
<
string
,
ISyncExtension
>
|
null
,
to
:
Map
<
string
,
ISyncExtension
>
,
ignoredExtensions
:
Set
<
string
>
):
{
added
:
Set
<
string
>
,
removed
:
Set
<
string
>
,
updated
:
Set
<
string
>
}
{
function
compare
(
from
:
Map
<
string
,
ISyncExtension
>
|
null
,
to
:
Map
<
string
,
ISyncExtension
>
,
ignoredExtensions
:
Set
<
string
>
,
{
checkInstalledProperty
}:
{
checkInstalledProperty
:
boolean
}
=
{
checkInstalledProperty
:
false
}
):
{
added
:
Set
<
string
>
,
removed
:
Set
<
string
>
,
updated
:
Set
<
string
>
}
{
const
fromKeys
=
from
?
keys
(
from
).
filter
(
key
=>
!
ignoredExtensions
.
has
(
key
))
:
[];
const
toKeys
=
keys
(
to
).
filter
(
key
=>
!
ignoredExtensions
.
has
(
key
));
const
added
=
toKeys
.
filter
(
key
=>
fromKeys
.
indexOf
(
key
)
===
-
1
).
reduce
((
r
,
key
)
=>
{
r
.
add
(
key
);
return
r
;
},
new
Set
<
string
>
());
...
...
@@ -170,6 +168,7 @@ function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISync
if
(
!
toExtension
||
fromExtension
.
disabled
!==
toExtension
.
disabled
||
fromExtension
.
version
!==
toExtension
.
version
||
(
checkInstalledProperty
&&
fromExtension
.
installed
!==
toExtension
.
installed
)
)
{
updated
.
add
(
key
);
}
...
...
@@ -177,3 +176,28 @@ function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISync
return
{
added
,
removed
,
updated
};
}
// massage incoming extension - add optional properties
function
massageIncomingExtension
(
extension
:
ISyncExtension
):
ISyncExtension
{
return
{
...
extension
,
...{
disabled
:
!!
extension
.
disabled
,
installed
:
!!
extension
.
installed
}
};
}
// massage outgoing extension - remove optional properties
function
massageOutgoingExtension
(
extension
:
ISyncExtension
,
key
:
string
):
ISyncExtension
{
const
massagedExtension
:
ISyncExtension
=
{
identifier
:
{
id
:
extension
.
identifier
.
id
,
uuid
:
startsWith
(
key
,
'
uuid:
'
)
?
key
.
substring
(
'
uuid:
'
.
length
)
:
undefined
},
};
if
(
extension
.
disabled
)
{
massagedExtension
.
disabled
=
true
;
}
if
(
extension
.
installed
)
{
massagedExtension
.
installed
=
true
;
}
if
(
extension
.
version
)
{
massagedExtension
.
version
=
extension
.
version
;
}
return
massagedExtension
;
}
src/vs/platform/userDataSync/common/extensionsSync.ts
浏览文件 @
240d1b73
...
...
@@ -41,7 +41,10 @@ interface ILastSyncUserData extends IRemoteUserData {
export
class
ExtensionsSynchroniser
extends
AbstractSynchroniser
implements
IUserDataSynchroniser
{
private
static
readonly
EXTENSIONS_DATA_URI
=
URI
.
from
({
scheme
:
USER_DATA_SYNC_SCHEME
,
authority
:
'
extensions
'
,
path
:
`/current.json`
});
protected
readonly
version
:
number
=
2
;
/*
Version 3 - Introduce installed property to skip installing built in extensions
*/
protected
readonly
version
:
number
=
3
;
protected
isEnabled
():
boolean
{
return
super
.
isEnabled
()
&&
this
.
extensionGalleryService
.
isEnabled
();
}
constructor
(
...
...
@@ -85,7 +88,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
if
(
remoteUserData
.
syncData
!==
null
)
{
const
localExtensions
=
await
this
.
getLocalExtensions
();
const
remoteExtensions
=
this
.
pars
eExtensions
(
remoteUserData
.
syncData
);
const
remoteExtensions
=
await
this
.
parseAndMigrat
eExtensions
(
remoteUserData
.
syncData
);
const
{
added
,
updated
,
remote
,
removed
}
=
merge
(
localExtensions
,
remoteExtensions
,
localExtensions
,
[],
this
.
getIgnoredExtensions
());
await
this
.
apply
({
added
,
removed
,
updated
,
remote
,
remoteUserData
,
localExtensions
,
skippedExtensions
:
[],
lastSyncUserData
,
...
...
@@ -204,7 +207,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
protected
async
performReplace
(
syncData
:
ISyncData
,
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
ILastSyncUserData
|
null
):
Promise
<
void
>
{
const
localExtensions
=
await
this
.
getLocalExtensions
();
const
syncExtensions
=
this
.
pars
eExtensions
(
syncData
);
const
syncExtensions
=
await
this
.
parseAndMigrat
eExtensions
(
syncData
);
const
{
added
,
updated
,
removed
}
=
merge
(
localExtensions
,
syncExtensions
,
localExtensions
,
[],
this
.
getIgnoredExtensions
());
await
this
.
apply
({
...
...
@@ -215,8 +218,8 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
}
protected
async
generatePreview
(
remoteUserData
:
IRemoteUserData
,
lastSyncUserData
:
ILastSyncUserData
|
null
):
Promise
<
IExtensionsSyncPreviewResult
>
{
const
remoteExtensions
:
ISyncExtension
[]
|
null
=
remoteUserData
.
syncData
?
this
.
pars
eExtensions
(
remoteUserData
.
syncData
)
:
null
;
const
lastSyncExtensions
:
ISyncExtension
[]
|
null
=
lastSyncUserData
?
this
.
pars
eExtensions
(
lastSyncUserData
.
syncData
!
)
:
null
;
const
remoteExtensions
:
ISyncExtension
[]
|
null
=
remoteUserData
.
syncData
?
await
this
.
parseAndMigrat
eExtensions
(
remoteUserData
.
syncData
)
:
null
;
const
lastSyncExtensions
:
ISyncExtension
[]
|
null
=
lastSyncUserData
?
await
this
.
parseAndMigrat
eExtensions
(
lastSyncUserData
.
syncData
!
)
:
null
;
const
skippedExtensions
:
ISyncExtension
[]
=
lastSyncUserData
?
lastSyncUserData
.
skippedExtensions
||
[]
:
[];
const
localExtensions
=
await
this
.
getLocalExtensions
();
...
...
@@ -353,31 +356,50 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
return
newSkippedExtensions
;
}
private
parseExtensions
(
syncData
:
ISyncData
):
ISyncExtension
[]
{
let
extensions
:
ISyncExtension
[]
=
JSON
.
parse
(
syncData
.
content
);
if
(
syncData
.
version
===
1
)
{
extensions
=
extensions
.
map
(
e
=>
{
private
async
parseAndMigrateExtensions
(
syncData
:
ISyncData
):
Promise
<
ISyncExtension
[]
>
{
const
extensions
=
this
.
parseExtensions
(
syncData
);
if
(
syncData
.
version
===
1
||
syncData
.
version
===
2
)
{
const
systemExtensions
=
await
this
.
extensionManagementService
.
getInstalled
(
ExtensionType
.
System
);
for
(
const
extension
of
extensions
)
{
// #region Migration from v1 (enabled -> disabled)
if
((
<
any
>
e
).
enabled
===
false
)
{
e
.
disabled
=
true
;
if
(
syncData
.
version
===
1
)
{
if
((
<
any
>
extension
).
enabled
===
false
)
{
extension
.
disabled
=
true
;
}
delete
(
<
any
>
extension
).
enabled
;
}
delete
(
<
any
>
e
).
enabled
;
// #endregion
return
e
;
});
// #region Migration from v2 (set installed property on extension)
if
(
syncData
.
version
===
2
)
{
if
(
systemExtensions
.
every
(
installed
=>
!
areSameExtensions
(
installed
.
identifier
,
extension
.
identifier
)))
{
extension
.
installed
=
true
;
}
}
// #endregion
}
}
return
extensions
;
}
private
parseExtensions
(
syncData
:
ISyncData
):
ISyncExtension
[]
{
return
JSON
.
parse
(
syncData
.
content
);
}
private
async
getLocalExtensions
():
Promise
<
ISyncExtension
[]
>
{
const
installedExtensions
=
await
this
.
extensionManagementService
.
getInstalled
();
const
disabledExtensions
=
this
.
extensionEnablementService
.
getDisabledExtensions
();
return
installedExtensions
.
map
(({
identifier
})
=>
{
.
map
(({
identifier
,
type
})
=>
{
const
syncExntesion
:
ISyncExtension
=
{
identifier
};
if
(
disabledExtensions
.
some
(
disabledExtension
=>
areSameExtensions
(
disabledExtension
,
identifier
)))
{
syncExntesion
.
disabled
=
true
;
}
if
(
type
===
ExtensionType
.
User
)
{
syncExntesion
.
installed
=
true
;
}
return
syncExntesion
;
});
}
...
...
src/vs/platform/userDataSync/common/userDataSync.ts
浏览文件 @
240d1b73
...
...
@@ -239,6 +239,7 @@ export interface ISyncExtension {
identifier
:
IExtensionIdentifier
;
version
?:
string
;
disabled
?:
boolean
;
installed
?:
boolean
;
}
export
interface
IStorageValue
{
...
...
src/vs/platform/userDataSync/test/common/extensionsMerge.test.ts
浏览文件 @
240d1b73
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录