Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
1d229976
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,发现更多精彩内容 >>
未验证
提交
1d229976
编写于
11月 22, 2018
作者:
B
Benjamin Pasero
提交者:
GitHub
11月 22, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #63651 from Microsoft/ben/storagehint
Refactor storage service and improve perf
上级
4ab4252e
fcfab425
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
331 addition
and
281 deletion
+331
-281
src/tsconfig.strictNullChecks.json
src/tsconfig.strictNullChecks.json
+1
-1
src/vs/base/node/storage.ts
src/vs/base/node/storage.ts
+24
-5
src/vs/platform/storage/node/storageService.ts
src/vs/platform/storage/node/storageService.ts
+249
-33
src/vs/platform/storage/test/node/storageService.test.ts
src/vs/platform/storage/test/node/storageService.test.ts
+20
-7
src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts
.../telemetry/test/electron-browser/commonProperties.test.ts
+8
-8
src/vs/platform/workspaces/common/workspaces.ts
src/vs/platform/workspaces/common/workspaces.ts
+10
-0
src/vs/workbench/electron-browser/main.ts
src/vs/workbench/electron-browser/main.ts
+11
-198
src/vs/workbench/electron-browser/shell.ts
src/vs/workbench/electron-browser/shell.ts
+1
-6
src/vs/workbench/services/configuration/node/configurationService.ts
...bench/services/configuration/node/configurationService.ts
+1
-10
src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts
...ration/test/electron-browser/configurationService.test.ts
+2
-1
src/vs/workbench/services/workspace/node/workspaceEditingService.ts
...kbench/services/workspace/node/workspaceEditingService.ts
+3
-11
src/vs/workbench/test/workbenchTestServices.ts
src/vs/workbench/test/workbenchTestServices.ts
+1
-1
未找到文件。
src/tsconfig.strictNullChecks.json
浏览文件 @
1d229976
...
...
@@ -510,7 +510,7 @@
"./vs/platform/statusbar/common/statusbar.ts"
,
"./vs/platform/storage/common/storage.ts"
,
"./vs/platform/storage/common/storageLegacyService.ts"
,
"./vs/platform/storage/node/storageService.ts"
,
//
"./vs/platform/storage/node/storageService.ts"
,
TODO@Ben
bring
back
when
storageMigration
is
removed
"./vs/platform/telemetry/browser/errorTelemetry.ts"
,
"./vs/platform/telemetry/common/telemetry.ts"
,
"./vs/platform/telemetry/common/telemetryService.ts"
,
...
...
src/vs/base/node/storage.ts
浏览文件 @
1d229976
...
...
@@ -13,9 +13,20 @@ import { basename } from 'path';
import
{
mark
}
from
'
vs/base/common/performance
'
;
import
{
rename
,
unlinkIgnoreError
,
copy
,
renameIgnoreError
}
from
'
vs/base/node/pfs
'
;
export
enum
StorageHint
{
// A hint to the storage that the storage
// does not exist on disk yet. This allows
// the storage library to improve startup
// time by not checking the storage for data.
STORAGE_DOES_NOT_EXIST
}
export
interface
IStorageOptions
{
path
:
string
;
hint
?:
StorageHint
;
logging
?:
IStorageLoggingOptions
;
}
...
...
@@ -58,6 +69,8 @@ export interface IStorage extends IDisposable {
export
class
Storage
extends
Disposable
implements
IStorage
{
_serviceBrand
:
any
;
static
IN_MEMORY_PATH
=
'
:memory:
'
;
private
static
readonly
FLUSH_DELAY
=
100
;
private
_onDidChangeStorage
:
Emitter
<
string
>
=
this
.
_register
(
new
Emitter
<
string
>
());
...
...
@@ -73,7 +86,7 @@ export class Storage extends Disposable implements IStorage {
private
pendingDeletes
:
Set
<
string
>
=
new
Set
<
string
>
();
private
pendingInserts
:
Map
<
string
,
string
>
=
new
Map
();
constructor
(
options
:
IStorageOptions
)
{
constructor
(
private
options
:
IStorageOptions
)
{
super
();
this
.
storage
=
new
SQLiteStorageImpl
(
options
);
...
...
@@ -92,6 +105,13 @@ export class Storage extends Disposable implements IStorage {
this
.
state
=
StorageState
.
Initialized
;
if
(
this
.
options
.
hint
===
StorageHint
.
STORAGE_DOES_NOT_EXIST
)
{
// return early if we know the storage file does not exist. this is a performance
// optimization to not load all items of the underlying storage if we know that
// there can be no items because the storage does not exist.
return
Promise
.
resolve
();
}
return
this
.
storage
.
getItems
().
then
(
items
=>
{
this
.
cache
=
items
;
});
...
...
@@ -239,7 +259,6 @@ export class SQLiteStorageImpl {
private
static
measuredRequireDuration
:
boolean
;
// TODO@Ben remove me after a while
private
static
IN_MEMORY_PATH
=
'
:memory:
'
;
private
static
BUSY_OPEN_TIMEOUT
=
2000
;
// timeout in ms to retry when opening DB fails with SQLITE_BUSY
private
name
:
string
;
...
...
@@ -323,7 +342,7 @@ export class SQLiteStorageImpl {
// If the DB closed successfully and we are not running in-memory
// make a backup of the DB so that we can use it as fallback in
// case the actual DB becomes corrupt.
if
(
result
.
path
!==
S
QLiteStorageImpl
.
IN_MEMORY_PATH
)
{
if
(
result
.
path
!==
S
torage
.
IN_MEMORY_PATH
)
{
return
this
.
backup
(
result
).
then
(
resolve
,
error
=>
{
this
.
logger
.
error
(
`[storage
${
this
.
name
}
] backup():
${
error
}
`
);
...
...
@@ -338,7 +357,7 @@ export class SQLiteStorageImpl {
}
private
backup
(
db
:
IOpenDatabaseResult
):
Promise
<
void
>
{
if
(
db
.
path
===
S
QLiteStorageImpl
.
IN_MEMORY_PATH
)
{
if
(
db
.
path
===
S
torage
.
IN_MEMORY_PATH
)
{
return
Promise
.
resolve
();
// no backups when running in-memory
}
...
...
@@ -371,7 +390,7 @@ export class SQLiteStorageImpl {
// In case of any error to open the DB, use an in-memory
// DB so that we always have a valid DB to talk to.
this
.
doOpen
(
S
QLiteStorageImpl
.
IN_MEMORY_PATH
).
then
(
resolve
,
reject
);
this
.
doOpen
(
S
torage
.
IN_MEMORY_PATH
).
then
(
resolve
,
reject
);
};
this
.
doOpen
(
path
).
then
(
resolve
,
error
=>
{
...
...
src/vs/platform/storage/node/storageService.ts
浏览文件 @
1d229976
...
...
@@ -7,21 +7,31 @@ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import
{
Event
,
Emitter
}
from
'
vs/base/common/event
'
;
import
{
ILogService
,
LogLevel
}
from
'
vs/platform/log/common/log
'
;
import
{
IWorkspaceStorageChangeEvent
,
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
Storage
,
IStorageLoggingOptions
,
NullStorage
,
IStorage
}
from
'
vs/base/node/storage
'
;
import
{
Storage
,
IStorageLoggingOptions
,
NullStorage
,
IStorage
,
StorageHint
}
from
'
vs/base/node/storage
'
;
import
{
IStorageLegacyService
,
StorageLegacyScope
}
from
'
vs/platform/storage/common/storageLegacyService
'
;
import
{
startsWith
}
from
'
vs/base/common/strings
'
;
import
{
startsWith
,
endsWith
}
from
'
vs/base/common/strings
'
;
import
{
Action
}
from
'
vs/base/common/actions
'
;
import
{
IWindowService
}
from
'
vs/platform/windows/common/windows
'
;
import
{
localize
}
from
'
vs/nls
'
;
import
{
mark
,
getDuration
}
from
'
vs/base/common/performance
'
;
import
{
join
,
basename
}
from
'
path
'
;
import
{
copy
}
from
'
vs/base/node/pfs
'
;
import
{
join
}
from
'
path
'
;
import
{
copy
,
exists
,
mkdirp
,
readdir
,
writeFile
}
from
'
vs/base/node/pfs
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IWorkspaceInitializationPayload
,
isWorkspaceIdentifier
,
isSingleFolderWorkspaceInitializationPayload
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
import
{
StorageObject
,
parseMultiRootStorage
,
parseFolderStorage
,
parseNoWorkspaceStorage
,
parseEmptyStorage
}
from
'
vs/platform/storage/common/storageLegacyMigration
'
;
export
interface
IStorageServiceOptions
{
storeInMemory
?:
boolean
;
disableGlobalStorage
?:
boolean
;
}
export
class
StorageService
extends
Disposable
implements
IStorageService
{
_serviceBrand
:
any
;
static
IN_MEMORY_PATH
=
'
:memory:
'
;
private
static
WORKSPACE_STORAGE_NAME
=
'
storage.db
'
;
private
static
WORKSPACE_META_NAME
=
'
workspace.json
'
;
private
_onDidChangeStorage
:
Emitter
<
IWorkspaceStorageChangeEvent
>
=
this
.
_register
(
new
Emitter
<
IWorkspaceStorageChangeEvent
>
());
get
onDidChangeStorage
():
Event
<
IWorkspaceStorageChangeEvent
>
{
return
this
.
_onDidChangeStorage
.
event
;
}
...
...
@@ -60,9 +70,9 @@ export class StorageService extends Disposable implements IStorageService {
private
loggingOptions
:
IStorageLoggingOptions
;
constructor
(
workspaceStoragePath
:
string
,
disableGlobalStorage
:
boolean
,
@
I
LogService
logService
:
ILog
Service
private
options
:
IStorageServiceOptions
,
@
ILogService
private
logService
:
ILogService
,
@
I
EnvironmentService
private
environmentService
:
IEnvironment
Service
)
{
super
();
...
...
@@ -81,14 +91,191 @@ export class StorageService extends Disposable implements IStorageService {
}
};
this
.
globalStorageWorkspacePath
=
workspaceStoragePath
===
StorageService
.
IN_MEMORY_PATH
?
StorageService
.
IN_MEMORY_PATH
:
StorageService
.
IN_MEMORY_PATH
;
this
.
globalStorage
=
disableGlobalStorage
?
new
NullStorage
()
:
new
Storage
({
path
:
this
.
globalStorageWorkspacePath
,
logging
:
this
.
loggingOptions
});
// Global Storage
this
.
globalStorageWorkspacePath
=
options
.
storeInMemory
?
Storage
.
IN_MEMORY_PATH
:
Storage
.
IN_MEMORY_PATH
;
this
.
globalStorage
=
options
.
disableGlobalStorage
?
new
NullStorage
()
:
new
Storage
({
path
:
this
.
globalStorageWorkspacePath
,
logging
:
this
.
loggingOptions
});
this
.
_register
(
this
.
globalStorage
.
onDidChangeStorage
(
key
=>
this
.
handleDidChangeStorage
(
key
,
StorageScope
.
GLOBAL
)));
this
.
createWorkspaceStorage
(
workspaceStoragePath
);
// Workspace Storage (in-memory only, other users require the initalize() call)
if
(
options
.
storeInMemory
)
{
this
.
createWorkspaceStorage
(
Storage
.
IN_MEMORY_PATH
,
StorageHint
.
STORAGE_DOES_NOT_EXIST
);
}
}
private
handleDidChangeStorage
(
key
:
string
,
scope
:
StorageScope
):
void
{
this
.
_onDidChangeStorage
.
fire
({
key
,
scope
});
}
initialize
(
payload
:
IWorkspaceInitializationPayload
):
Thenable
<
void
>
{
// Prepare workspace storage folder for DB
return
this
.
prepareWorkspaceStorageFolder
(
payload
).
then
(
result
=>
{
let
workspaceStoragePath
:
string
;
let
workspaceStorageExists
:
Thenable
<
boolean
>
;
if
(
this
.
options
.
storeInMemory
)
{
workspaceStoragePath
=
Storage
.
IN_MEMORY_PATH
;
workspaceStorageExists
=
Promise
.
resolve
(
true
);
}
else
{
workspaceStoragePath
=
join
(
result
.
path
,
StorageService
.
WORKSPACE_STORAGE_NAME
);
mark
(
'
willCheckWorkspaceStorageExists
'
);
workspaceStorageExists
=
exists
(
workspaceStoragePath
).
then
(
exists
=>
{
mark
(
'
didCheckWorkspaceStorageExists
'
);
return
exists
;
});
}
return
workspaceStorageExists
.
then
(
exists
=>
{
// Create workspace storage and initalize
mark
(
'
willInitWorkspaceStorage
'
);
return
this
.
createWorkspaceStorage
(
workspaceStoragePath
,
result
.
wasCreated
?
StorageHint
.
STORAGE_DOES_NOT_EXIST
:
void
0
).
init
().
then
(()
=>
{
mark
(
'
didInitWorkspaceStorage
'
);
// Migrate storage if this is the first start and we are not using in-memory
let
migrationPromise
:
Thenable
<
void
>
;
if
(
!
this
.
options
.
storeInMemory
&&
!
exists
)
{
migrationPromise
=
this
.
migrateWorkspaceStorage
(
payload
);
}
else
{
migrationPromise
=
Promise
.
resolve
();
}
return
migrationPromise
.
then
(()
=>
{
mark
(
'
willInitGlobalStorage
'
);
return
this
.
globalStorage
.
init
().
then
(()
=>
{
mark
(
'
didInitGlobalStorage
'
);
});
});
});
});
});
}
// TODO@Ben remove migration after a while
private
migrateWorkspaceStorage
(
payload
:
IWorkspaceInitializationPayload
):
Thenable
<
void
>
{
mark
(
'
willMigrateWorkspaceStorageKeys
'
);
return
readdir
(
this
.
environmentService
.
extensionsPath
).
then
(
extensions
=>
{
// Otherwise, we migrate data from window.localStorage over
try
{
let
workspaceItems
:
StorageObject
;
if
(
isWorkspaceIdentifier
(
payload
))
{
workspaceItems
=
parseMultiRootStorage
(
window
.
localStorage
,
`root:
${
payload
.
id
}
`
);
}
else
if
(
isSingleFolderWorkspaceInitializationPayload
(
payload
))
{
workspaceItems
=
parseFolderStorage
(
window
.
localStorage
,
payload
.
folder
.
toString
());
}
else
{
if
(
payload
.
id
===
'
ext-dev
'
)
{
workspaceItems
=
parseNoWorkspaceStorage
(
window
.
localStorage
);
}
else
{
workspaceItems
=
parseEmptyStorage
(
window
.
localStorage
,
`
${
payload
.
id
}
`
);
}
}
const
workspaceItemsKeys
=
workspaceItems
?
Object
.
keys
(
workspaceItems
)
:
[];
if
(
workspaceItemsKeys
.
length
>
0
)
{
const
supportedKeys
=
new
Map
<
string
,
string
>
();
[
'
workbench.search.history
'
,
'
history.entries
'
,
'
ignoreNetVersionError
'
,
'
ignoreEnospcError
'
,
'
extensionUrlHandler.urlToHandle
'
,
'
terminal.integrated.isWorkspaceShellAllowed
'
,
'
workbench.tasks.ignoreTask010Shown
'
,
'
workbench.tasks.recentlyUsedTasks
'
,
'
workspaces.dontPromptToOpen
'
,
'
output.activechannel
'
,
'
outline/state
'
,
'
extensionsAssistant/workspaceRecommendationsIgnore
'
,
'
extensionsAssistant/dynamicWorkspaceRecommendations
'
,
'
debug.repl.history
'
,
'
editor.matchCase
'
,
'
editor.wholeWord
'
,
'
editor.isRegex
'
,
'
lifecyle.lastShutdownReason
'
,
'
debug.selectedroot
'
,
'
debug.selectedconfigname
'
,
'
debug.breakpoint
'
,
'
debug.breakpointactivated
'
,
'
debug.functionbreakpoint
'
,
'
debug.exceptionbreakpoint
'
,
'
debug.watchexpressions
'
,
'
workbench.sidebar.activeviewletid
'
,
'
workbench.panelpart.activepanelid
'
,
'
workbench.zenmode.active
'
,
'
workbench.centerededitorlayout.active
'
,
'
workbench.sidebar.restore
'
,
'
workbench.sidebar.hidden
'
,
'
workbench.panel.hidden
'
,
'
workbench.panel.location
'
,
'
extensionsIdentifiers/disabled
'
,
'
extensionsIdentifiers/enabled
'
,
'
scm.views
'
,
'
suggest/memories/first
'
,
'
suggest/memories/recentlyUsed
'
,
'
suggest/memories/recentlyUsedByPrefix
'
,
'
workbench.view.explorer.numberOfVisibleViews
'
,
'
workbench.view.extensions.numberOfVisibleViews
'
,
'
workbench.view.debug.numberOfVisibleViews
'
,
'
workbench.explorer.views.state
'
,
'
workbench.view.extensions.state
'
,
'
workbench.view.debug.state
'
,
'
memento/workbench.editor.walkThroughPart
'
,
'
memento/workbench.editor.settings2
'
,
'
memento/workbench.editor.htmlPreviewPart
'
,
'
memento/workbench.editor.defaultPreferences
'
,
'
memento/workbench.editors.files.textFileEditor
'
,
'
memento/workbench.editors.logViewer
'
,
'
memento/workbench.editors.textResourceEditor
'
,
'
memento/workbench.panel.output
'
].
forEach
(
key
=>
supportedKeys
.
set
(
key
.
toLowerCase
(),
key
));
// Support extension storage as well (always the ID of the extension)
extensions
.
forEach
(
extension
=>
{
let
extensionId
:
string
;
if
(
extension
.
indexOf
(
'
-
'
)
>=
0
)
{
extensionId
=
extension
.
substring
(
0
,
extension
.
lastIndexOf
(
'
-
'
));
// convert "author.extension-0.2.5" => "author.extension"
}
else
{
extensionId
=
extension
;
}
if
(
extensionId
)
{
supportedKeys
.
set
(
extensionId
.
toLowerCase
(),
extensionId
);
}
});
workspaceItemsKeys
.
forEach
(
key
=>
{
const
value
=
workspaceItems
[
key
];
// first check for a well known supported key and store with realcase value
const
supportedKey
=
supportedKeys
.
get
(
key
);
if
(
supportedKey
)
{
this
.
store
(
supportedKey
,
value
,
StorageScope
.
WORKSPACE
);
}
// fix lowercased ".numberOfVisibleViews"
else
if
(
endsWith
(
key
,
'
.numberOfVisibleViews
'
.
toLowerCase
()))
{
const
normalizedKey
=
key
.
substring
(
0
,
key
.
length
-
'
.numberOfVisibleViews
'
.
length
)
+
'
.numberOfVisibleViews
'
;
this
.
store
(
normalizedKey
,
value
,
StorageScope
.
WORKSPACE
);
}
// support dynamic keys
else
if
(
key
.
indexOf
(
'
memento/
'
)
===
0
||
key
.
indexOf
(
'
viewservice.
'
)
===
0
||
endsWith
(
key
,
'
.state
'
))
{
this
.
store
(
key
,
value
,
StorageScope
.
WORKSPACE
);
}
});
}
}
catch
(
error
)
{
onUnexpectedError
(
error
);
this
.
logService
.
error
(
error
);
}
mark
(
'
didMigrateWorkspaceStorageKeys
'
);
});
}
private
createWorkspaceStorage
(
workspaceStoragePath
:
string
):
void
{
private
createWorkspaceStorage
(
workspaceStoragePath
:
string
,
hint
?:
StorageHint
):
IStorage
{
// Dispose old (if any)
this
.
workspaceStorage
=
dispose
(
this
.
workspaceStorage
);
...
...
@@ -96,26 +283,54 @@ export class StorageService extends Disposable implements IStorageService {
// Create new
this
.
workspaceStoragePath
=
workspaceStoragePath
;
this
.
workspaceStorage
=
new
Storage
({
path
:
workspaceStoragePath
,
logging
:
this
.
loggingOptions
});
this
.
workspaceStorage
=
new
Storage
({
path
:
workspaceStoragePath
,
logging
:
this
.
loggingOptions
,
hint
});
this
.
workspaceStorageListener
=
this
.
workspaceStorage
.
onDidChangeStorage
(
key
=>
this
.
handleDidChangeStorage
(
key
,
StorageScope
.
WORKSPACE
));
return
this
.
workspaceStorage
;
}
private
handleDidChangeStorage
(
key
:
string
,
scope
:
StorageScope
):
void
{
this
.
_onDidChangeStorage
.
fire
({
key
,
scope
})
;
private
getWorkspaceStorageFolderPath
(
payload
:
IWorkspaceInitializationPayload
):
string
{
return
join
(
this
.
environmentService
.
workspaceStorageHome
,
payload
.
id
);
// workspace home + workspace id
;
}
init
():
Promise
<
void
>
{
mark
(
'
willInitWorkspaceStorage
'
);
return
this
.
workspaceStorage
.
init
().
then
(()
=>
{
mark
(
'
didInitWorkspaceStorage
'
);
private
prepareWorkspaceStorageFolder
(
payload
:
IWorkspaceInitializationPayload
):
Thenable
<
{
path
:
string
,
wasCreated
:
boolean
}
>
{
const
workspaceStorageFolderPath
=
this
.
getWorkspaceStorageFolderPath
(
payload
);
mark
(
'
willInitGlobalStorage
'
);
return
this
.
globalStorage
.
init
().
then
(()
=>
{
mark
(
'
didInitGlobalStorage
'
);
return
exists
(
workspaceStorageFolderPath
).
then
(
exists
=>
{
if
(
exists
)
{
return
{
path
:
workspaceStorageFolderPath
,
wasCreated
:
false
};
}
return
mkdirp
(
workspaceStorageFolderPath
).
then
(()
=>
{
// Write metadata into folder
this
.
ensureWorkspaceStorageFolderMeta
(
payload
);
return
{
path
:
workspaceStorageFolderPath
,
wasCreated
:
true
};
});
});
}
private
ensureWorkspaceStorageFolderMeta
(
payload
:
IWorkspaceInitializationPayload
):
void
{
let
meta
:
object
|
undefined
=
void
0
;
if
(
isSingleFolderWorkspaceInitializationPayload
(
payload
))
{
meta
=
{
folder
:
payload
.
folder
.
toString
()
};
}
else
if
(
isWorkspaceIdentifier
(
payload
))
{
meta
=
{
configuration
:
payload
.
configPath
};
}
if
(
meta
)
{
const
workspaceStorageMetaPath
=
join
(
this
.
getWorkspaceStorageFolderPath
(
payload
),
StorageService
.
WORKSPACE_META_NAME
);
exists
(
workspaceStorageMetaPath
).
then
(
exists
=>
{
if
(
exists
)
{
return
void
0
;
// already existing
}
return
writeFile
(
workspaceStorageMetaPath
,
JSON
.
stringify
(
meta
,
void
0
,
2
));
}).
then
(
null
,
error
=>
onUnexpectedError
(
error
));
}
}
get
(
key
:
string
,
scope
:
StorageScope
,
fallbackValue
:
string
):
string
;
get
(
key
:
string
,
scope
:
StorageScope
):
string
|
undefined
;
get
(
key
:
string
,
scope
:
StorageScope
,
fallbackValue
?:
string
):
string
|
undefined
{
...
...
@@ -217,23 +432,24 @@ export class StorageService extends Disposable implements IStorageService {
});
}
migrate
(
toWorkspace
StorageFolder
:
string
):
Thenable
<
void
>
{
if
(
this
.
workspaceStoragePath
===
Storage
Service
.
IN_MEMORY_PATH
)
{
migrate
(
toWorkspace
:
IWorkspaceInitializationPayload
):
Thenable
<
void
>
{
if
(
this
.
workspaceStoragePath
===
Storage
.
IN_MEMORY_PATH
)
{
return
Promise
.
resolve
();
// no migration needed if running in memory
}
// Compute new workspace storage path based on workspace identifier
const
newWorkspaceStoragePath
=
join
(
toWorkspaceStorageFolder
,
basename
(
this
.
workspaceStoragePath
));
if
(
this
.
workspaceStoragePath
===
newWorkspaceStoragePath
)
{
return
Promise
.
resolve
();
// guard against migrating to same path
}
// Close workspace DB to be able to copy
return
this
.
workspaceStorage
.
close
().
then
(()
=>
{
return
copy
(
this
.
workspaceStoragePath
,
newWorkspaceStoragePath
).
then
(()
=>
{
this
.
createWorkspaceStorage
(
newWorkspaceStoragePath
);
return
this
.
workspaceStorage
.
init
();
// Prepare new workspace storage folder
return
this
.
prepareWorkspaceStorageFolder
(
toWorkspace
).
then
(
result
=>
{
const
newWorkspaceStoragePath
=
join
(
result
.
path
,
StorageService
.
WORKSPACE_STORAGE_NAME
);
// Copy current storage over to new workspace storage
return
copy
(
this
.
workspaceStoragePath
,
newWorkspaceStoragePath
).
then
(()
=>
{
// Recreate and init workspace storage
return
this
.
createWorkspaceStorage
(
newWorkspaceStoragePath
).
init
();
});
});
});
}
...
...
src/vs/platform/storage/test/node/storageService.test.ts
浏览文件 @
1d229976
...
...
@@ -12,6 +12,8 @@ import { join } from 'path';
import
{
tmpdir
}
from
'
os
'
;
import
{
mkdirp
,
del
}
from
'
vs/base/node/pfs
'
;
import
{
NullLogService
}
from
'
vs/platform/log/common/log
'
;
import
{
EnvironmentService
}
from
'
vs/platform/environment/node/environmentService
'
;
import
{
parseArgs
}
from
'
vs/platform/environment/node/argv
'
;
suite
(
'
StorageService
'
,
()
=>
{
...
...
@@ -81,27 +83,38 @@ suite('StorageService', () => {
}
test
(
'
Migrate Data
'
,
async
()
=>
{
class
StorageTestEnvironmentService
extends
EnvironmentService
{
constructor
(
private
workspaceStorageFolderPath
:
string
,
private
_extensionsPath
)
{
super
(
parseArgs
(
process
.
argv
),
process
.
execPath
);
}
get
workspaceStorageHome
():
string
{
return
this
.
workspaceStorageFolderPath
;
}
get
extensionsPath
():
string
{
return
this
.
_extensionsPath
;
}
}
const
storageDir
=
uniqueStorageDir
();
await
mkdirp
(
storageDir
);
const
storage
=
new
StorageService
(
join
(
storageDir
,
'
storage.db
'
),
false
,
new
NullLogService
(
));
await
storage
.
init
(
);
const
storage
=
new
StorageService
(
{},
new
NullLogService
(),
new
StorageTestEnvironmentService
(
storageDir
,
storageDir
));
await
storage
.
init
ialize
({
id
:
String
(
Date
.
now
())
}
);
storage
.
store
(
'
bar
'
,
'
foo
'
,
StorageScope
.
WORKSPACE
);
storage
.
store
(
'
barNumber
'
,
55
,
StorageScope
.
WORKSPACE
);
storage
.
store
(
'
barBoolean
'
,
true
,
StorageScope
.
GLOBAL
);
const
newStorageDir
=
uniqueStorageDir
();
await
mkdirp
(
newStorageDir
);
await
storage
.
migrate
(
newStorageDir
);
await
storage
.
migrate
({
id
:
String
(
Date
.
now
()
+
100
)
});
equal
(
storage
.
get
(
'
bar
'
,
StorageScope
.
WORKSPACE
),
'
foo
'
);
equal
(
storage
.
getInteger
(
'
barNumber
'
,
StorageScope
.
WORKSPACE
),
55
);
equal
(
storage
.
getBoolean
(
'
barBoolean
'
,
StorageScope
.
GLOBAL
),
true
);
await
storage
.
close
();
await
del
(
newStorageDir
,
tmpdir
());
await
del
(
storageDir
,
tmpdir
());
});
});
\ No newline at end of file
src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts
浏览文件 @
1d229976
...
...
@@ -7,7 +7,7 @@ import * as path from 'path';
import
*
as
os
from
'
os
'
;
import
*
as
fs
from
'
fs
'
;
import
{
resolveWorkbenchCommonProperties
}
from
'
vs/platform/telemetry/node/workbenchCommonProperties
'
;
import
{
getRandomTestPath
}
from
'
vs/workbench/test/workbenchTestServices
'
;
import
{
getRandomTestPath
,
TestEnvironmentService
}
from
'
vs/workbench/test/workbenchTestServices
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
StorageService
}
from
'
vs/platform/storage/node/storageService
'
;
import
{
NullLogService
}
from
'
vs/platform/log/common/log
'
;
...
...
@@ -21,10 +21,10 @@ suite('Telemetry - common properties', function () {
const
commit
:
string
=
void
0
;
const
version
:
string
=
void
0
;
let
nestStorage2
Service
:
IStorageService
;
let
testStorage
Service
:
IStorageService
;
setup
(()
=>
{
nestStorage2Service
=
new
StorageService
(
'
:memory:
'
,
false
,
new
NullLogService
()
);
testStorageService
=
new
StorageService
({
storeInMemory
:
true
},
new
NullLogService
(),
TestEnvironmentService
);
});
teardown
(
done
=>
{
...
...
@@ -34,7 +34,7 @@ suite('Telemetry - common properties', function () {
test
(
'
default
'
,
async
function
()
{
await
mkdirp
(
parentDir
);
fs
.
writeFileSync
(
installSource
,
'
my.install.source
'
);
const
props
=
await
resolveWorkbenchCommonProperties
(
nestStorage2
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
const
props
=
await
resolveWorkbenchCommonProperties
(
testStorage
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
assert
.
ok
(
'
commitHash
'
in
props
);
assert
.
ok
(
'
sessionID
'
in
props
);
assert
.
ok
(
'
timestamp
'
in
props
);
...
...
@@ -55,22 +55,22 @@ suite('Telemetry - common properties', function () {
assert
.
ok
(
'
common.instanceId
'
in
props
,
'
instanceId
'
);
assert
.
ok
(
'
common.machineId
'
in
props
,
'
machineId
'
);
fs
.
unlinkSync
(
installSource
);
const
props_1
=
await
resolveWorkbenchCommonProperties
(
nestStorage2
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
const
props_1
=
await
resolveWorkbenchCommonProperties
(
testStorage
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
assert
.
ok
(
!
(
'
common.source
'
in
props_1
));
});
test
(
'
lastSessionDate when aviablale
'
,
async
function
()
{
nestStorage2
Service
.
store
(
'
telemetry.lastSessionDate
'
,
new
Date
().
toUTCString
(),
StorageScope
.
GLOBAL
);
testStorage
Service
.
store
(
'
telemetry.lastSessionDate
'
,
new
Date
().
toUTCString
(),
StorageScope
.
GLOBAL
);
const
props
=
await
resolveWorkbenchCommonProperties
(
nestStorage2
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
const
props
=
await
resolveWorkbenchCommonProperties
(
testStorage
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
assert
.
ok
(
'
common.lastSessionDate
'
in
props
);
// conditional, see below
assert
.
ok
(
'
common.isNewSession
'
in
props
);
assert
.
equal
(
props
[
'
common.isNewSession
'
],
0
);
});
test
(
'
values chance on ask
'
,
async
function
()
{
const
props
=
await
resolveWorkbenchCommonProperties
(
nestStorage2
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
const
props
=
await
resolveWorkbenchCommonProperties
(
testStorage
Service
,
commit
,
version
,
'
someMachineId
'
,
installSource
);
let
value1
=
props
[
'
common.sequence
'
];
let
value2
=
props
[
'
common.sequence
'
];
assert
.
ok
(
value1
!==
value2
,
'
seq
'
);
...
...
src/vs/platform/workspaces/common/workspaces.ts
浏览文件 @
1d229976
...
...
@@ -128,3 +128,13 @@ export function toWorkspaceIdentifier(workspace: IWorkspace): IWorkspaceIdentifi
// Empty workspace
return
undefined
;
}
export
type
IMultiFolderWorkspaceInitializationPayload
=
IWorkspaceIdentifier
;
export
interface
ISingleFolderWorkspaceInitializationPayload
{
id
:
string
;
folder
:
ISingleFolderWorkspaceIdentifier
;
}
export
interface
IEmptyWorkspaceInitializationPayload
{
id
:
string
;
}
export
type
IWorkspaceInitializationPayload
=
IMultiFolderWorkspaceInitializationPayload
|
ISingleFolderWorkspaceInitializationPayload
|
IEmptyWorkspaceInitializationPayload
;
export
function
isSingleFolderWorkspaceInitializationPayload
(
obj
:
any
):
obj
is
ISingleFolderWorkspaceInitializationPayload
{
return
isSingleFolderWorkspaceIdentifier
((
obj
.
folder
as
ISingleFolderWorkspaceIdentifier
));
}
\ No newline at end of file
src/vs/workbench/electron-browser/main.ts
浏览文件 @
1d229976
...
...
@@ -13,10 +13,10 @@ import * as comparer from 'vs/base/common/comparers';
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
{
URI
as
uri
}
from
'
vs/base/common/uri
'
;
import
{
IWorkspaceContextService
,
Workspace
,
WorkbenchState
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
WorkspaceService
,
ISingleFolderWorkspaceInitializationPayload
,
IMultiFolderWorkspaceInitializationPayload
,
IEmptyWorkspaceInitializationPayload
,
IWorkspaceInitializationPayload
,
isSingleFolderWorkspaceInitializationPayload
}
from
'
vs/workbench/services/configuration/node/configurationService
'
;
import
{
WorkspaceService
}
from
'
vs/workbench/services/configuration/node/configurationService
'
;
import
{
SyncDescriptor
}
from
'
vs/platform/instantiation/common/descriptors
'
;
import
{
ServiceCollection
}
from
'
vs/platform/instantiation/common/serviceCollection
'
;
import
{
stat
,
exists
,
writeFile
,
readdir
}
from
'
vs/base/node/pfs
'
;
import
{
stat
}
from
'
vs/base/node/pfs
'
;
import
{
EnvironmentService
}
from
'
vs/platform/environment/node/environmentService
'
;
import
*
as
gracefulFs
from
'
graceful-fs
'
;
import
{
KeyboardMapperFactory
}
from
'
vs/workbench/services/keybinding/electron-browser/keybindingService
'
;
...
...
@@ -31,7 +31,7 @@ import { IUpdateService } from 'vs/platform/update/common/update';
import
{
URLHandlerChannel
,
URLServiceChannelClient
}
from
'
vs/platform/url/node/urlIpc
'
;
import
{
IURLService
}
from
'
vs/platform/url/common/url
'
;
import
{
WorkspacesChannelClient
}
from
'
vs/platform/workspaces/node/workspacesIpc
'
;
import
{
IWorkspacesService
,
ISingleFolderWorkspaceIdentifier
,
isWorkspaceIdentifier
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
IWorkspacesService
,
ISingleFolderWorkspaceIdentifier
,
IWorkspaceInitializationPayload
,
IMultiFolderWorkspaceInitializationPayload
,
IEmptyWorkspaceInitializationPayload
,
ISingleFolderWorkspaceInitializationPayload
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
createSpdLogService
}
from
'
vs/platform/log/node/spdlogService
'
;
import
*
as
fs
from
'
fs
'
;
import
{
ConsoleLogService
,
MultiplexLogService
,
ILogService
}
from
'
vs/platform/log/common/log
'
;
...
...
@@ -43,12 +43,9 @@ import { RelayURLService } from 'vs/platform/url/common/urlService';
import
{
MenubarChannelClient
}
from
'
vs/platform/menubar/node/menubarIpc
'
;
import
{
IMenubarService
}
from
'
vs/platform/menubar/common/menubar
'
;
import
{
Schemas
}
from
'
vs/base/common/network
'
;
import
{
sanitizeFilePath
,
mkdirp
}
from
'
vs/base/node/extfs
'
;
import
{
basename
,
join
}
from
'
path
'
;
import
{
sanitizeFilePath
}
from
'
vs/base/node/extfs
'
;
import
{
basename
}
from
'
path
'
;
import
{
createHash
}
from
'
crypto
'
;
import
{
StorageObject
,
parseFolderStorage
,
parseMultiRootStorage
,
parseNoWorkspaceStorage
,
parseEmptyStorage
}
from
'
vs/platform/storage/common/storageLegacyMigration
'
;
import
{
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
endsWith
}
from
'
vs/base/common/strings
'
;
import
{
IdleValue
}
from
'
vs/base/common/async
'
;
import
{
setGlobalLeakWarningThreshold
}
from
'
vs/base/common/event
'
;
...
...
@@ -139,11 +136,6 @@ function openWorkbench(configuration: IWindowConfiguration): Promise<void> {
storageService
},
mainServices
,
mainProcessClient
,
configuration
);
// Store meta file in workspace storage after workbench is running
shell
.
onRunning
(()
=>
{
ensureWorkspaceStorageFolderMeta
(
payload
,
workspaceService
,
environmentService
);
});
// Gracefully Shutdown Storage
shell
.
onShutdown
(
event
=>
{
event
.
join
(
storageService
.
close
());
...
...
@@ -247,196 +239,17 @@ function createWorkspaceService(payload: IWorkspaceInitializationPayload, enviro
}
function
createStorageService
(
payload
:
IWorkspaceInitializationPayload
,
environmentService
:
IEnvironmentService
,
logService
:
ILogService
):
Thenable
<
StorageService
>
{
const
useInMemoryStorage
=
!!
environmentService
.
extensionTestsPath
;
// no storage during extension tests!
const
storageService
=
new
StorageService
({
disableGlobalStorage
:
true
,
storeInMemory
:
useInMemoryStorage
},
logService
,
environmentService
);
// Prepare the workspace storage folder
return
prepareWorkspaceStorageFolder
(
payload
,
environmentService
).
then
(
result
=>
{
// Return early if we are using in-memory storage
const
useInMemoryStorage
=
!!
environmentService
.
extensionTestsPath
;
/* never keep any state when running extension tests */
if
(
useInMemoryStorage
)
{
const
storageService
=
new
StorageService
(
StorageService
.
IN_MEMORY_PATH
,
true
,
logService
);
return
storageService
.
init
().
then
(()
=>
storageService
);
}
// Otherwise do a migration of previous workspace data if the DB does not exist yet
// TODO@Ben remove me after some milestones
const
workspaceStorageDBPath
=
join
(
result
.
path
,
'
storage.db
'
);
perf
.
mark
(
'
willCheckWorkspaceStorageExists
'
);
return
exists
(
workspaceStorageDBPath
).
then
(
exists
=>
{
perf
.
mark
(
'
didCheckWorkspaceStorageExists
'
);
const
storageService
=
new
StorageService
(
workspaceStorageDBPath
,
true
,
logService
);
return
storageService
.
init
().
then
(()
=>
{
if
(
exists
)
{
return
storageService
;
// return early if DB was already there
}
perf
.
mark
(
'
willMigrateWorkspaceStorageKeys
'
);
return
readdir
(
environmentService
.
extensionsPath
).
then
(
extensions
=>
{
// Otherwise, we migrate data from window.localStorage over
try
{
let
workspaceItems
:
StorageObject
;
if
(
isWorkspaceIdentifier
(
payload
))
{
workspaceItems
=
parseMultiRootStorage
(
window
.
localStorage
,
`root:
${
payload
.
id
}
`
);
}
else
if
(
isSingleFolderWorkspaceInitializationPayload
(
payload
))
{
workspaceItems
=
parseFolderStorage
(
window
.
localStorage
,
payload
.
folder
.
toString
());
}
else
{
if
(
payload
.
id
===
'
ext-dev
'
)
{
workspaceItems
=
parseNoWorkspaceStorage
(
window
.
localStorage
);
}
else
{
workspaceItems
=
parseEmptyStorage
(
window
.
localStorage
,
`
${
payload
.
id
}
`
);
}
}
const
workspaceItemsKeys
=
workspaceItems
?
Object
.
keys
(
workspaceItems
)
:
[];
if
(
workspaceItemsKeys
.
length
>
0
)
{
const
supportedKeys
=
new
Map
<
string
,
string
>
();
[
'
workbench.search.history
'
,
'
history.entries
'
,
'
ignoreNetVersionError
'
,
'
ignoreEnospcError
'
,
'
extensionUrlHandler.urlToHandle
'
,
'
terminal.integrated.isWorkspaceShellAllowed
'
,
'
workbench.tasks.ignoreTask010Shown
'
,
'
workbench.tasks.recentlyUsedTasks
'
,
'
workspaces.dontPromptToOpen
'
,
'
output.activechannel
'
,
'
outline/state
'
,
'
extensionsAssistant/workspaceRecommendationsIgnore
'
,
'
extensionsAssistant/dynamicWorkspaceRecommendations
'
,
'
debug.repl.history
'
,
'
editor.matchCase
'
,
'
editor.wholeWord
'
,
'
editor.isRegex
'
,
'
lifecyle.lastShutdownReason
'
,
'
debug.selectedroot
'
,
'
debug.selectedconfigname
'
,
'
debug.breakpoint
'
,
'
debug.breakpointactivated
'
,
'
debug.functionbreakpoint
'
,
'
debug.exceptionbreakpoint
'
,
'
debug.watchexpressions
'
,
'
workbench.sidebar.activeviewletid
'
,
'
workbench.panelpart.activepanelid
'
,
'
workbench.zenmode.active
'
,
'
workbench.centerededitorlayout.active
'
,
'
workbench.sidebar.restore
'
,
'
workbench.sidebar.hidden
'
,
'
workbench.panel.hidden
'
,
'
workbench.panel.location
'
,
'
extensionsIdentifiers/disabled
'
,
'
extensionsIdentifiers/enabled
'
,
'
scm.views
'
,
'
suggest/memories/first
'
,
'
suggest/memories/recentlyUsed
'
,
'
suggest/memories/recentlyUsedByPrefix
'
,
'
workbench.view.explorer.numberOfVisibleViews
'
,
'
workbench.view.extensions.numberOfVisibleViews
'
,
'
workbench.view.debug.numberOfVisibleViews
'
,
'
workbench.explorer.views.state
'
,
'
workbench.view.extensions.state
'
,
'
workbench.view.debug.state
'
,
'
memento/workbench.editor.walkThroughPart
'
,
'
memento/workbench.editor.settings2
'
,
'
memento/workbench.editor.htmlPreviewPart
'
,
'
memento/workbench.editor.defaultPreferences
'
,
'
memento/workbench.editors.files.textFileEditor
'
,
'
memento/workbench.editors.logViewer
'
,
'
memento/workbench.editors.textResourceEditor
'
,
'
memento/workbench.panel.output
'
].
forEach
(
key
=>
supportedKeys
.
set
(
key
.
toLowerCase
(),
key
));
// Support extension storage as well (always the ID of the extension)
extensions
.
forEach
(
extension
=>
{
let
extensionId
:
string
;
if
(
extension
.
indexOf
(
'
-
'
)
>=
0
)
{
extensionId
=
extension
.
substring
(
0
,
extension
.
lastIndexOf
(
'
-
'
));
// convert "author.extension-0.2.5" => "author.extension"
}
else
{
extensionId
=
extension
;
}
if
(
extensionId
)
{
supportedKeys
.
set
(
extensionId
.
toLowerCase
(),
extensionId
);
}
});
workspaceItemsKeys
.
forEach
(
key
=>
{
const
value
=
workspaceItems
[
key
];
// first check for a well known supported key and store with realcase value
const
supportedKey
=
supportedKeys
.
get
(
key
);
if
(
supportedKey
)
{
storageService
.
store
(
supportedKey
,
value
,
StorageScope
.
WORKSPACE
);
}
// fix lowercased ".numberOfVisibleViews"
else
if
(
endsWith
(
key
,
'
.numberOfVisibleViews
'
.
toLowerCase
()))
{
const
normalizedKey
=
key
.
substring
(
0
,
key
.
length
-
'
.numberOfVisibleViews
'
.
length
)
+
'
.numberOfVisibleViews
'
;
storageService
.
store
(
normalizedKey
,
value
,
StorageScope
.
WORKSPACE
);
}
// support dynamic keys
else
if
(
key
.
indexOf
(
'
memento/
'
)
===
0
||
key
.
indexOf
(
'
viewservice.
'
)
===
0
||
endsWith
(
key
,
'
.state
'
))
{
storageService
.
store
(
key
,
value
,
StorageScope
.
WORKSPACE
);
}
});
}
}
catch
(
error
)
{
onUnexpectedError
(
error
);
logService
.
error
(
error
);
}
perf
.
mark
(
'
didMigrateWorkspaceStorageKeys
'
);
return
storageService
;
});
});
});
});
}
function
getWorkspaceStoragePath
(
payload
:
IWorkspaceInitializationPayload
,
environmentService
:
IEnvironmentService
):
string
{
return
join
(
environmentService
.
workspaceStorageHome
,
payload
.
id
);
// workspace home + workspace id;
}
function
prepareWorkspaceStorageFolder
(
payload
:
IWorkspaceInitializationPayload
,
environmentService
:
IEnvironmentService
):
Thenable
<
{
path
:
string
,
wasCreated
:
boolean
}
>
{
const
workspaceStoragePath
=
getWorkspaceStoragePath
(
payload
,
environmentService
);
return
exists
(
workspaceStoragePath
).
then
(
exists
=>
{
if
(
exists
)
{
return
{
path
:
workspaceStoragePath
,
wasCreated
:
false
};
}
return
storageService
.
initialize
(
payload
).
then
(()
=>
storageService
,
error
=>
{
onUnexpectedError
(
error
);
logService
.
error
(
error
);
return
mkdirp
(
workspaceStoragePath
).
then
(()
=>
({
path
:
workspaceStoragePath
,
wasCreated
:
true
}))
;
return
storageService
;
});
}
function
ensureWorkspaceStorageFolderMeta
(
payload
:
IWorkspaceInitializationPayload
,
workspaceService
:
IWorkspaceContextService
,
environmentService
:
IEnvironmentService
):
void
{
const
state
=
workspaceService
.
getWorkbenchState
();
if
(
state
===
WorkbenchState
.
EMPTY
)
{
return
;
// no storage meta for empty workspaces
}
const
workspaceStorageMetaPath
=
join
(
getWorkspaceStoragePath
(
payload
,
environmentService
),
'
workspace.json
'
);
exists
(
workspaceStorageMetaPath
).
then
(
exists
=>
{
if
(
exists
)
{
return
void
0
;
// already existing
}
const
workspace
=
workspaceService
.
getWorkspace
();
return
writeFile
(
workspaceStorageMetaPath
,
JSON
.
stringify
({
configuration
:
workspace
.
configuration
?
uri
.
revive
(
workspace
.
configuration
).
toString
()
:
void
0
,
folder
:
state
===
WorkbenchState
.
FOLDER
?
uri
.
revive
(
workspace
.
folders
[
0
].
uri
).
toString
()
:
void
0
},
undefined
,
2
));
}).
then
(
null
,
error
=>
onUnexpectedError
(
error
));
}
function
createStorageLegacyService
(
workspaceService
:
IWorkspaceContextService
,
environmentService
:
IEnvironmentService
):
IStorageLegacyService
{
let
workspaceId
:
string
;
...
...
src/vs/workbench/electron-browser/shell.ts
浏览文件 @
1d229976
...
...
@@ -126,9 +126,6 @@ export class WorkbenchShell extends Disposable {
private
readonly
_onShutdown
=
this
.
_register
(
new
Emitter
<
ShutdownEvent
>
());
get
onShutdown
():
Event
<
ShutdownEvent
>
{
return
this
.
_onShutdown
.
event
;
}
private
readonly
_onRunning
=
this
.
_register
(
new
Emitter
<
void
>
());
get
onRunning
():
Event
<
void
>
{
return
this
.
_onRunning
.
event
;
}
private
storageService
:
DelegatingStorageService
;
private
environmentService
:
IEnvironmentService
;
private
logService
:
ILogService
;
...
...
@@ -217,10 +214,8 @@ export class WorkbenchShell extends Disposable {
// Startup Workbench
workbench
.
startup
().
then
(
startupInfos
=>
{
// Set lifecycle phase to `Runnning` so that other contributions can
// now do something we also emit this as event to interested parties outside
// Set lifecycle phase to `Runnning`
this
.
lifecycleService
.
phase
=
LifecyclePhase
.
Running
;
this
.
_onRunning
.
fire
();
// Startup Telemetry
this
.
logStartupTelemetry
(
startupInfos
);
...
...
src/vs/workbench/services/configuration/node/configurationService.ts
浏览文件 @
1d229976
...
...
@@ -23,7 +23,7 @@ import { Configuration, WorkspaceConfigurationChangeEvent, AllKeysConfigurationC
import
{
IWorkspaceConfigurationService
,
FOLDER_CONFIG_FOLDER_NAME
,
defaultSettingsSchemaId
,
userSettingsSchemaId
,
workspaceSettingsSchemaId
,
folderSettingsSchemaId
}
from
'
vs/workbench/services/configuration/common/configuration
'
;
import
{
Registry
}
from
'
vs/platform/registry/common/platform
'
;
import
{
IConfigurationNode
,
IConfigurationRegistry
,
Extensions
,
IConfigurationPropertySchema
,
allSettings
,
windowSettings
,
resourceSettings
,
applicationSettings
}
from
'
vs/platform/configuration/common/configurationRegistry
'
;
import
{
IWorkspaceIdentifier
,
isWorkspaceIdentifier
,
IStoredWorkspaceFolder
,
isStoredWorkspaceFolder
,
IWorkspaceFolderCreationData
,
ISingleFolderWorkspaceIdentifier
,
isSingleFolderWorkspaceIdentifier
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
IWorkspaceIdentifier
,
isWorkspaceIdentifier
,
IStoredWorkspaceFolder
,
isStoredWorkspaceFolder
,
IWorkspaceFolderCreationData
,
ISingleFolderWorkspaceIdentifier
,
isSingleFolderWorkspaceIdentifier
,
IWorkspaceInitializationPayload
,
isSingleFolderWorkspaceInitializationPayload
,
ISingleFolderWorkspaceInitializationPayload
,
IEmptyWorkspaceInitializationPayload
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
IExtensionService
}
from
'
vs/workbench/services/extensions/common/extensions
'
;
import
{
ICommandService
}
from
'
vs/platform/commands/common/commands
'
;
import
product
from
'
vs/platform/node/product
'
;
...
...
@@ -38,15 +38,6 @@ import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import
{
localize
}
from
'
vs/nls
'
;
import
{
isEqual
}
from
'
vs/base/common/resources
'
;
export
type
IMultiFolderWorkspaceInitializationPayload
=
IWorkspaceIdentifier
;
export
interface
ISingleFolderWorkspaceInitializationPayload
{
id
:
string
;
folder
:
ISingleFolderWorkspaceIdentifier
;
}
export
interface
IEmptyWorkspaceInitializationPayload
{
id
:
string
;
}
export
type
IWorkspaceInitializationPayload
=
IMultiFolderWorkspaceInitializationPayload
|
ISingleFolderWorkspaceInitializationPayload
|
IEmptyWorkspaceInitializationPayload
;
export
function
isSingleFolderWorkspaceInitializationPayload
(
obj
:
any
):
obj
is
ISingleFolderWorkspaceInitializationPayload
{
return
isSingleFolderWorkspaceIdentifier
((
obj
.
folder
as
ISingleFolderWorkspaceIdentifier
));
}
export
class
WorkspaceService
extends
Disposable
implements
IWorkspaceConfigurationService
,
IWorkspaceContextService
{
public
_serviceBrand
:
any
;
...
...
src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts
浏览文件 @
1d229976
...
...
@@ -16,7 +16,8 @@ import { parseArgs } from 'vs/platform/environment/node/argv';
import
*
as
pfs
from
'
vs/base/node/pfs
'
;
import
*
as
uuid
from
'
vs/base/common/uuid
'
;
import
{
IConfigurationRegistry
,
Extensions
as
ConfigurationExtensions
,
ConfigurationScope
}
from
'
vs/platform/configuration/common/configurationRegistry
'
;
import
{
WorkspaceService
,
ISingleFolderWorkspaceInitializationPayload
}
from
'
vs/workbench/services/configuration/node/configurationService
'
;
import
{
WorkspaceService
}
from
'
vs/workbench/services/configuration/node/configurationService
'
;
import
{
ISingleFolderWorkspaceInitializationPayload
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
ConfigurationEditingErrorCode
}
from
'
vs/workbench/services/configuration/node/configurationEditingService
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
IWorkspaceContextService
,
WorkbenchState
,
IWorkspaceFoldersChangeEvent
}
from
'
vs/platform/workspace/common/workspace
'
;
...
...
src/vs/workbench/services/workspace/node/workspaceEditingService.ts
浏览文件 @
1d229976
...
...
@@ -25,9 +25,6 @@ import { distinct } from 'vs/base/common/arrays';
import
{
isLinux
}
from
'
vs/base/common/platform
'
;
import
{
isEqual
}
from
'
vs/base/common/resources
'
;
import
{
INotificationService
,
Severity
}
from
'
vs/platform/notification/common/notification
'
;
import
{
join
}
from
'
path
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
mkdirp
}
from
'
vs/base/node/pfs
'
;
export
class
WorkspaceEditingService
implements
IWorkspaceEditingService
{
...
...
@@ -42,8 +39,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
@
IExtensionService
private
extensionService
:
IExtensionService
,
@
IBackupFileService
private
backupFileService
:
IBackupFileService
,
@
INotificationService
private
notificationService
:
INotificationService
,
@
ICommandService
private
commandService
:
ICommandService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
@
ICommandService
private
commandService
:
ICommandService
)
{
}
...
...
@@ -243,13 +239,9 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
}
private
migrateStorage
(
toWorkspace
:
IWorkspaceIdentifier
):
Thenable
<
void
>
{
const
newWorkspaceStorageHome
=
join
(
this
.
environmentService
.
workspaceStorageHome
,
toWorkspace
.
id
)
;
const
storageImpl
=
this
.
storageService
as
DelegatingStorageService
;
return
mkdirp
(
newWorkspaceStorageHome
).
then
(()
=>
{
const
storageImpl
=
this
.
storageService
as
DelegatingStorageService
;
return
storageImpl
.
storage
.
migrate
(
newWorkspaceStorageHome
);
});
return
storageImpl
.
storage
.
migrate
(
toWorkspace
);
}
private
migrateWorkspaceSettings
(
toWorkspace
:
IWorkspaceIdentifier
):
TPromise
<
void
>
{
...
...
src/vs/workbench/test/workbenchTestServices.ts
浏览文件 @
1d229976
...
...
@@ -532,7 +532,7 @@ export class TestPartService implements IPartService {
export
class
TestStorageService
extends
StorageService
{
constructor
()
{
super
(
'
:memory:
'
,
false
,
new
NullLogService
()
);
super
(
{
storeInMemory
:
true
},
new
NullLogService
(),
TestEnvironmentService
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录