Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
d5349d2b
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,发现更多精彩内容 >>
提交
d5349d2b
编写于
12月 02, 2016
作者:
D
Daniel Imms
提交者:
GitHub
12月 02, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #16303 from Microsoft/tyriar/hot_exit/empty_workspaces
Hot exit empty workspace support
上级
4bcb8538
ef4b5102
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
570 addition
and
310 deletion
+570
-310
src/vs/code/electron-main/main.ts
src/vs/code/electron-main/main.ts
+5
-0
src/vs/code/electron-main/windows.ts
src/vs/code/electron-main/windows.ts
+18
-8
src/vs/platform/backup/common/backup.ts
src/vs/platform/backup/common/backup.ts
+15
-16
src/vs/platform/backup/common/backupIpc.ts
src/vs/platform/backup/common/backupIpc.ts
+37
-0
src/vs/platform/backup/electron-main/backupMainService.ts
src/vs/platform/backup/electron-main/backupMainService.ts
+78
-29
src/vs/platform/backup/test/electron-main/backupMainService.test.ts
...tform/backup/test/electron-main/backupMainService.test.ts
+233
-86
src/vs/test/utils/servicesTestUtils.ts
src/vs/test/utils/servicesTestUtils.ts
+4
-4
src/vs/workbench/electron-browser/main.ts
src/vs/workbench/electron-browser/main.ts
+0
-1
src/vs/workbench/electron-browser/shell.ts
src/vs/workbench/electron-browser/shell.ts
+6
-0
src/vs/workbench/electron-browser/workbench.ts
src/vs/workbench/electron-browser/workbench.ts
+4
-4
src/vs/workbench/parts/backup/common/backupModelTracker.ts
src/vs/workbench/parts/backup/common/backupModelTracker.ts
+2
-2
src/vs/workbench/parts/backup/common/backupRestorer.ts
src/vs/workbench/parts/backup/common/backupRestorer.ts
+2
-2
src/vs/workbench/services/backup/common/backup.ts
src/vs/workbench/services/backup/common/backup.ts
+2
-2
src/vs/workbench/services/backup/node/backupFileService.ts
src/vs/workbench/services/backup/node/backupFileService.ts
+12
-16
src/vs/workbench/services/backup/node/backupModelService.ts
src/vs/workbench/services/backup/node/backupModelService.ts
+4
-12
src/vs/workbench/services/backup/test/backupFileService.test.ts
.../workbench/services/backup/test/backupFileService.test.ts
+142
-122
src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts
...nfiguration/test/node/configurationEditingService.test.ts
+2
-2
src/vs/workbench/services/textfile/browser/textFileService.ts
...vs/workbench/services/textfile/browser/textFileService.ts
+2
-2
src/vs/workbench/services/textfile/electron-browser/textFileService.ts
...nch/services/textfile/electron-browser/textFileService.ts
+2
-2
未找到文件。
src/vs/code/electron-main/main.ts
浏览文件 @
d5349d2b
...
@@ -35,6 +35,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
...
@@ -35,6 +35,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import
{
ILogService
,
MainLogService
}
from
'
vs/code/electron-main/log
'
;
import
{
ILogService
,
MainLogService
}
from
'
vs/code/electron-main/log
'
;
import
{
IStorageService
,
StorageService
}
from
'
vs/code/electron-main/storage
'
;
import
{
IStorageService
,
StorageService
}
from
'
vs/code/electron-main/storage
'
;
import
{
IBackupMainService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
IBackupMainService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
BackupChannel
}
from
'
vs/platform/backup/common/backupIpc
'
;
import
{
BackupMainService
}
from
'
vs/platform/backup/electron-main/backupMainService
'
;
import
{
BackupMainService
}
from
'
vs/platform/backup/electron-main/backupMainService
'
;
import
{
IEnvironmentService
,
ParsedArgs
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IEnvironmentService
,
ParsedArgs
}
from
'
vs/platform/environment/common/environment
'
;
import
{
EnvironmentService
}
from
'
vs/platform/environment/node/environmentService
'
;
import
{
EnvironmentService
}
from
'
vs/platform/environment/node/environmentService
'
;
...
@@ -185,6 +186,10 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo
...
@@ -185,6 +186,10 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo
const
urlChannel
=
instantiationService2
.
createInstance
(
URLChannel
,
urlService
);
const
urlChannel
=
instantiationService2
.
createInstance
(
URLChannel
,
urlService
);
electronIpcServer
.
registerChannel
(
'
url
'
,
urlChannel
);
electronIpcServer
.
registerChannel
(
'
url
'
,
urlChannel
);
const
backupService
=
accessor
.
get
(
IBackupMainService
);
const
backupChannel
=
instantiationService2
.
createInstance
(
BackupChannel
,
backupService
);
electronIpcServer
.
registerChannel
(
'
backup
'
,
backupChannel
);
const
windowsService
=
accessor
.
get
(
IWindowsService
);
const
windowsService
=
accessor
.
get
(
IWindowsService
);
const
windowsChannel
=
new
WindowsChannel
(
windowsService
);
const
windowsChannel
=
new
WindowsChannel
(
windowsService
);
electronIpcServer
.
registerChannel
(
'
windows
'
,
windowsChannel
);
electronIpcServer
.
registerChannel
(
'
windows
'
,
windowsChannel
);
...
...
src/vs/code/electron-main/windows.ts
浏览文件 @
d5349d2b
...
@@ -29,7 +29,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
...
@@ -29,7 +29,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import
{
IWindowSettings
}
from
'
vs/platform/windows/common/windows
'
;
import
{
IWindowSettings
}
from
'
vs/platform/windows/common/windows
'
;
import
CommonEvent
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
CommonEvent
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
product
from
'
vs/platform/product
'
;
import
product
from
'
vs/platform/product
'
;
import
Uri
from
'
vs/base/common/uri
'
;
enum
WindowError
{
enum
WindowError
{
UNRESPONSIVE
,
UNRESPONSIVE
,
...
@@ -331,10 +330,11 @@ export class WindowsManager implements IWindowsMainService {
...
@@ -331,10 +330,11 @@ export class WindowsManager implements IWindowsMainService {
}
}
let
foldersToOpen
=
arrays
.
distinct
(
iPathsToOpen
.
filter
(
iPath
=>
iPath
.
workspacePath
&&
!
iPath
.
filePath
).
map
(
iPath
=>
iPath
.
workspacePath
),
folder
=>
platform
.
isLinux
?
folder
:
folder
.
toLowerCase
());
// prevent duplicates
let
foldersToOpen
=
arrays
.
distinct
(
iPathsToOpen
.
filter
(
iPath
=>
iPath
.
workspacePath
&&
!
iPath
.
filePath
).
map
(
iPath
=>
iPath
.
workspacePath
),
folder
=>
platform
.
isLinux
?
folder
:
folder
.
toLowerCase
());
// prevent duplicates
let
foldersToRestore
=
(
openConfig
.
initialStartup
&&
!
openConfig
.
cli
.
extensionDevelopmentPath
)
?
this
.
backupService
.
getWorkspaceBackupPaths
()
:
[];
let
foldersToRestore
=
(
openConfig
.
initialStartup
&&
!
openConfig
.
cli
.
extensionDevelopmentPath
)
?
this
.
backupService
.
workspaceBackupPaths
:
[];
let
filesToOpen
:
IPath
[]
=
[];
let
filesToOpen
:
IPath
[]
=
[];
let
filesToDiff
:
IPath
[]
=
[];
let
filesToDiff
:
IPath
[]
=
[];
let
emptyToOpen
=
iPathsToOpen
.
filter
(
iPath
=>
!
iPath
.
workspacePath
&&
!
iPath
.
filePath
);
let
emptyToOpen
=
iPathsToOpen
.
filter
(
iPath
=>
!
iPath
.
workspacePath
&&
!
iPath
.
filePath
);
let
emptyToRestore
=
(
openConfig
.
initialStartup
&&
!
openConfig
.
cli
.
extensionDevelopmentPath
)
?
this
.
backupService
.
emptyWorkspaceBackupPaths
:
[];
let
filesToCreate
=
iPathsToOpen
.
filter
(
iPath
=>
!!
iPath
.
filePath
&&
iPath
.
createFilePath
);
let
filesToCreate
=
iPathsToOpen
.
filter
(
iPath
=>
!!
iPath
.
filePath
&&
iPath
.
createFilePath
);
// Diff mode needs special care
// Diff mode needs special care
...
@@ -441,7 +441,17 @@ export class WindowsManager implements IWindowsMainService {
...
@@ -441,7 +441,17 @@ export class WindowsManager implements IWindowsMainService {
}
}
// Handle empty
// Handle empty
if
(
emptyToOpen
.
length
>
0
)
{
if
(
emptyToRestore
.
length
>
0
)
{
emptyToRestore
.
forEach
(
emptyWorkspaceBackupFolder
=>
{
const
configuration
=
this
.
toConfiguration
(
openConfig
,
null
,
null
,
null
,
null
);
const
browserWindow
=
this
.
openInBrowserWindow
(
configuration
,
true
/* new window */
,
null
,
emptyWorkspaceBackupFolder
);
usedWindows
.
push
(
browserWindow
);
openInNewWindow
=
true
;
// any other folders to open must open in new window then
});
}
// Only open empty if no empty workspaces were restored
else
if
(
emptyToOpen
.
length
>
0
)
{
emptyToOpen
.
forEach
(()
=>
{
emptyToOpen
.
forEach
(()
=>
{
const
configuration
=
this
.
toConfiguration
(
openConfig
);
const
configuration
=
this
.
toConfiguration
(
openConfig
);
const
browserWindow
=
this
.
openInBrowserWindow
(
configuration
,
openInNewWindow
,
openInNewWindow
?
void
0
:
openConfig
.
windowToUse
);
const
browserWindow
=
this
.
openInBrowserWindow
(
configuration
,
openInNewWindow
,
openInNewWindow
?
void
0
:
openConfig
.
windowToUse
);
...
@@ -468,10 +478,6 @@ export class WindowsManager implements IWindowsMainService {
...
@@ -468,10 +478,6 @@ export class WindowsManager implements IWindowsMainService {
}
}
}
}
// Register new paths for backup
if
(
!
openConfig
.
cli
.
extensionDevelopmentPath
)
{
this
.
backupService
.
pushWorkspaceBackupPathsSync
(
iPathsToOpen
.
filter
(
p
=>
p
.
workspacePath
).
map
(
p
=>
Uri
.
file
(
p
.
workspacePath
)));
}
// Emit events
// Emit events
this
.
_onPathsOpen
.
fire
(
iPathsToOpen
);
this
.
_onPathsOpen
.
fire
(
iPathsToOpen
);
...
@@ -711,7 +717,7 @@ export class WindowsManager implements IWindowsMainService {
...
@@ -711,7 +717,7 @@ export class WindowsManager implements IWindowsMainService {
return
[
Object
.
create
(
null
)];
return
[
Object
.
create
(
null
)];
}
}
private
openInBrowserWindow
(
configuration
:
IWindowConfiguration
,
forceNewWindow
?:
boolean
,
windowToUse
?:
VSCodeWindow
):
VSCodeWindow
{
private
openInBrowserWindow
(
configuration
:
IWindowConfiguration
,
forceNewWindow
?:
boolean
,
windowToUse
?:
VSCodeWindow
,
emptyWorkspaceBackupFolder
?:
string
):
VSCodeWindow
{
let
vscodeWindow
:
VSCodeWindow
;
let
vscodeWindow
:
VSCodeWindow
;
if
(
!
forceNewWindow
)
{
if
(
!
forceNewWindow
)
{
...
@@ -762,6 +768,10 @@ export class WindowsManager implements IWindowsMainService {
...
@@ -762,6 +768,10 @@ export class WindowsManager implements IWindowsMainService {
}
}
}
}
if
(
!
configuration
.
extensionDevelopmentPath
)
{
this
.
backupService
.
registerWindowForBackups
(
vscodeWindow
.
id
,
!
configuration
.
workspacePath
,
emptyWorkspaceBackupFolder
,
configuration
.
workspacePath
);
}
// Only load when the window has not vetoed this
// Only load when the window has not vetoed this
this
.
lifecycleService
.
unload
(
vscodeWindow
,
UnloadReason
.
LOAD
).
done
(
veto
=>
{
this
.
lifecycleService
.
unload
(
vscodeWindow
,
UnloadReason
.
LOAD
).
done
(
veto
=>
{
if
(
!
veto
)
{
if
(
!
veto
)
{
...
...
src/vs/platform/backup/common/backup.ts
浏览文件 @
d5349d2b
...
@@ -4,28 +4,27 @@
...
@@ -4,28 +4,27 @@
*--------------------------------------------------------------------------------------------*/
*--------------------------------------------------------------------------------------------*/
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
export
interface
IBackupWorkspacesFormat
{
export
interface
IBackupWorkspacesFormat
{
folderWorkspaces
:
string
[];
folderWorkspaces
:
string
[];
emptyWorkspaces
:
string
[];
}
}
export
const
IBackupMainService
=
createDecorator
<
IBackupMainService
>
(
'
backupService
'
);
export
const
IBackupMainService
=
createDecorator
<
IBackupMainService
>
(
'
backupMainService
'
);
export
const
IBackupService
=
createDecorator
<
IBackupService
>
(
'
backupService
'
);
export
interface
IBackupMainService
{
export
interface
IBackupMainService
extends
IBackupService
{
_serviceBrand
:
any
;
_serviceBrand
:
any
;
/**
workspaceBackupPaths
:
string
[];
* Gets the set of active workspace backup paths being tracked for restoration.
emptyWorkspaceBackupPaths
:
string
[];
*
* @return The set of active workspace backup paths being tracked for restoration.
registerWindowForBackups
(
windowId
:
number
,
isEmptyWorkspace
:
boolean
,
backupFolder
?:
string
,
workspacePath
?:
string
);
*/
getWorkspaceBackupPaths
():
string
[];
/**
* Pushes workspace backup paths to be tracked for restoration.
*
* @param workspaces The workspaces to add.
*/
pushWorkspaceBackupPathsSync
(
workspaces
:
Uri
[]):
void
;
}
}
export
interface
IBackupService
{
_serviceBrand
:
any
;
getBackupPath
(
windowId
:
number
):
TPromise
<
string
>
;
}
\ No newline at end of file
src/vs/platform/backup/common/backupIpc.ts
0 → 100644
浏览文件 @
d5349d2b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IChannel
}
from
'
vs/base/parts/ipc/common/ipc
'
;
import
{
IBackupService
}
from
'
./backup
'
;
export
interface
IBackupChannel
extends
IChannel
{
call
(
command
:
'
getBackupPath
'
,
arg
:
[
number
]):
TPromise
<
string
>
;
call
(
command
:
string
,
arg
?:
any
):
TPromise
<
any
>
;
}
export
class
BackupChannel
implements
IBackupChannel
{
constructor
(
private
service
:
IBackupService
)
{
}
call
(
command
:
string
,
arg
?:
any
):
TPromise
<
any
>
{
switch
(
command
)
{
case
'
getBackupPath
'
:
return
this
.
service
.
getBackupPath
(
arg
);
}
}
}
export
class
BackupChannelClient
implements
IBackupService
{
_serviceBrand
:
any
;
constructor
(
private
channel
:
IBackupChannel
)
{
}
getBackupPath
(
windowId
:
number
):
TPromise
<
string
>
{
return
this
.
channel
.
call
(
'
getBackupPath
'
,
windowId
);
}
}
\ No newline at end of file
src/vs/platform/backup/electron-main/backupMainService.ts
浏览文件 @
d5349d2b
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
*--------------------------------------------------------------------------------------------*/
import
*
as
arrays
from
'
vs/base/common/arrays
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
path
from
'
path
'
;
import
*
as
path
from
'
path
'
;
import
*
as
crypto
from
'
crypto
'
;
import
*
as
crypto
from
'
crypto
'
;
...
@@ -11,6 +12,7 @@ import * as extfs from 'vs/base/node/extfs';
...
@@ -11,6 +12,7 @@ import * as extfs from 'vs/base/node/extfs';
import
Uri
from
'
vs/base/common/uri
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
IBackupWorkspacesFormat
,
IBackupMainService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
IBackupWorkspacesFormat
,
IBackupMainService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
export
class
BackupMainService
implements
IBackupMainService
{
export
class
BackupMainService
implements
IBackupMainService
{
...
@@ -21,42 +23,65 @@ export class BackupMainService implements IBackupMainService {
...
@@ -21,42 +23,65 @@ export class BackupMainService implements IBackupMainService {
private
backups
:
IBackupWorkspacesFormat
;
private
backups
:
IBackupWorkspacesFormat
;
protected
mapWindowToBackupFolder
:
{
[
windowId
:
number
]:
string
;
};
constructor
(
constructor
(
@
IEnvironmentService
environmentService
:
IEnvironmentService
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
)
{
)
{
this
.
backupHome
=
environmentService
.
backupHome
;
this
.
backupHome
=
environmentService
.
backupHome
;
this
.
workspacesJsonPath
=
environmentService
.
backupWorkspacesPath
;
this
.
workspacesJsonPath
=
environmentService
.
backupWorkspacesPath
;
this
.
mapWindowToBackupFolder
=
Object
.
create
(
null
);
this
.
loadSync
();
this
.
loadSync
();
}
}
public
get
W
orkspaceBackupPaths
():
string
[]
{
public
get
w
orkspaceBackupPaths
():
string
[]
{
return
this
.
backups
.
folderWorkspaces
;
return
this
.
backups
.
folderWorkspaces
;
}
}
public
pushWorkspaceBackupPathsSync
(
workspaces
:
Uri
[]):
void
{
public
get
emptyWorkspaceBackupPaths
():
string
[]
{
let
needsSaving
=
false
;
return
this
.
backups
.
emptyWorkspaces
;
workspaces
.
forEach
(
workspace
=>
{
}
if
(
this
.
backups
.
folderWorkspaces
.
indexOf
(
workspace
.
fsPath
)
===
-
1
)
{
this
.
backups
.
folderWorkspaces
.
push
(
workspace
.
fsPath
);
needsSaving
=
true
;
}
});
if
(
needsSaving
)
{
public
getBackupPath
(
windowId
:
number
):
TPromise
<
string
>
{
if
(
!
this
.
mapWindowToBackupFolder
[
windowId
])
{
throw
new
Error
(
`Unknown backup workspace for window
${
windowId
}
`
);
}
return
TPromise
.
as
(
path
.
join
(
this
.
backupHome
,
this
.
mapWindowToBackupFolder
[
windowId
]));
}
public
registerWindowForBackups
(
windowId
:
number
,
isEmptyWorkspace
:
boolean
,
backupFolder
?:
string
,
workspacePath
?:
string
):
void
{
// Generate a new folder if this is a new empty workspace
if
(
isEmptyWorkspace
&&
!
backupFolder
)
{
backupFolder
=
Date
.
now
().
toString
();
}
this
.
mapWindowToBackupFolder
[
windowId
]
=
isEmptyWorkspace
?
backupFolder
:
this
.
getWorkspaceHash
(
workspacePath
);
this
.
pushBackupPathsSync
(
isEmptyWorkspace
?
backupFolder
:
workspacePath
,
isEmptyWorkspace
);
}
protected
pushBackupPathsSync
(
workspaceIdentifier
:
string
,
isEmptyWorkspace
:
boolean
):
void
{
if
(
!
isEmptyWorkspace
)
{
workspaceIdentifier
=
this
.
sanitizePath
(
workspaceIdentifier
);
}
const
array
=
isEmptyWorkspace
?
this
.
backups
.
emptyWorkspaces
:
this
.
backups
.
folderWorkspaces
;
if
(
array
.
indexOf
(
workspaceIdentifier
)
===
-
1
)
{
array
.
push
(
workspaceIdentifier
);
this
.
saveSync
();
this
.
saveSync
();
}
}
}
}
protected
removeWorkspaceBackupPathSync
(
workspace
:
Uri
):
void
{
protected
removeBackupPathSync
(
workspaceIdentifier
:
string
,
isEmptyWorkspace
:
boolean
):
void
{
if
(
!
this
.
backups
.
folderWorkspaces
)
{
const
array
=
isEmptyWorkspace
?
this
.
backups
.
emptyWorkspaces
:
this
.
backups
.
folderWorkspaces
;
if
(
!
array
)
{
return
;
return
;
}
}
const
index
=
this
.
backups
.
folderWorkspaces
.
indexOf
(
workspace
.
fsPath
);
const
index
=
array
.
indexOf
(
workspaceIdentifier
);
if
(
index
===
-
1
)
{
if
(
index
===
-
1
)
{
return
;
return
;
}
}
this
.
backups
.
folderWorkspaces
.
splice
(
index
,
1
);
array
.
splice
(
index
,
1
);
this
.
saveSync
();
this
.
saveSync
();
}
}
...
@@ -72,12 +97,20 @@ export class BackupMainService implements IBackupMainService {
...
@@ -72,12 +97,20 @@ export class BackupMainService implements IBackupMainService {
if
(
backups
.
folderWorkspaces
)
{
if
(
backups
.
folderWorkspaces
)
{
const
fws
=
backups
.
folderWorkspaces
;
const
fws
=
backups
.
folderWorkspaces
;
if
(
!
Array
.
isArray
(
fws
)
||
fws
.
some
(
f
=>
typeof
f
!==
'
string
'
))
{
if
(
!
Array
.
isArray
(
fws
)
||
fws
.
some
(
f
=>
typeof
f
!==
'
string
'
))
{
backups
=
Object
.
create
(
null
)
;
backups
.
folderWorkspaces
=
[]
;
}
}
}
else
{
backups
.
folderWorkspaces
=
[];
}
}
if
(
!
backups
.
folderWorkspaces
)
{
// Ensure emptyWorkspaces is a string[]
backups
.
folderWorkspaces
=
[];
if
(
backups
.
emptyWorkspaces
)
{
const
fws
=
backups
.
emptyWorkspaces
;
if
(
!
Array
.
isArray
(
fws
)
||
fws
.
some
(
f
=>
typeof
f
!==
'
string
'
))
{
backups
.
emptyWorkspaces
=
[];
}
}
else
{
backups
.
emptyWorkspaces
=
[];
}
}
this
.
backups
=
backups
;
this
.
backups
=
backups
;
...
@@ -86,21 +119,36 @@ export class BackupMainService implements IBackupMainService {
...
@@ -86,21 +119,36 @@ export class BackupMainService implements IBackupMainService {
this
.
validateBackupWorkspaces
(
backups
);
this
.
validateBackupWorkspaces
(
backups
);
}
}
protected
sanitizeFolderWorkspaces
(
backups
:
IBackupWorkspacesFormat
):
void
{
// Merge duplicates for folder workspaces, don't worry about cleaning them up as they will
// be removed when there are no backups.
backups
.
folderWorkspaces
=
arrays
.
distinct
(
backups
.
folderWorkspaces
.
map
(
w
=>
this
.
sanitizePath
(
w
)));
}
private
validateBackupWorkspaces
(
backups
:
IBackupWorkspacesFormat
):
void
{
private
validateBackupWorkspaces
(
backups
:
IBackupWorkspacesFormat
):
void
{
const
staleBackupWorkspaces
:
{
workspace
Path
:
string
;
backupPath
:
string
;
}[]
=
[];
const
staleBackupWorkspaces
:
{
workspace
Identifier
:
string
;
backupPath
:
string
;
isEmptyWorkspace
:
boolean
}[]
=
[];
const
backupWorkspaces
=
backups
.
folderWorkspaces
;
this
.
sanitizeFolderWorkspaces
(
backups
);
backupWorkspaces
.
forEach
(
workspacePath
=>
{
const
backupPath
=
this
.
toBackupPath
(
workspacePath
);
backups
.
folderWorkspaces
.
forEach
(
workspacePath
=>
{
const
backupPath
=
path
.
join
(
this
.
backupHome
,
this
.
getWorkspaceHash
(
workspacePath
));
if
(
!
this
.
hasBackupsSync
(
backupPath
))
{
const
backupWorkspace
=
this
.
sanitizePath
(
workspacePath
);
staleBackupWorkspaces
.
push
({
workspaceIdentifier
:
Uri
.
file
(
backupWorkspace
).
fsPath
,
backupPath
,
isEmptyWorkspace
:
false
});
}
});
backups
.
emptyWorkspaces
.
forEach
(
backupFolder
=>
{
const
backupPath
=
path
.
join
(
this
.
backupHome
,
backupFolder
);
if
(
!
this
.
hasBackupsSync
(
backupPath
))
{
if
(
!
this
.
hasBackupsSync
(
backupPath
))
{
staleBackupWorkspaces
.
push
({
workspace
Path
,
backupPath
});
staleBackupWorkspaces
.
push
({
workspace
Identifier
:
backupFolder
,
backupPath
,
isEmptyWorkspace
:
true
});
}
}
});
});
staleBackupWorkspaces
.
forEach
(
staleBackupWorkspace
=>
{
staleBackupWorkspaces
.
forEach
(
staleBackupWorkspace
=>
{
const
{
backupPath
,
workspace
Path
}
=
staleBackupWorkspace
;
const
{
backupPath
,
workspace
Identifier
,
isEmptyWorkspace
}
=
staleBackupWorkspace
;
extfs
.
delSync
(
backupPath
);
extfs
.
delSync
(
backupPath
);
this
.
remove
WorkspaceBackupPathSync
(
Uri
.
file
(
workspacePath
)
);
this
.
remove
BackupPathSync
(
workspaceIdentifier
,
isEmptyWorkspace
);
});
});
}
}
...
@@ -135,10 +183,11 @@ export class BackupMainService implements IBackupMainService {
...
@@ -135,10 +183,11 @@ export class BackupMainService implements IBackupMainService {
}
}
}
}
pr
otected
toBackupPath
(
workspacePath
:
string
):
string
{
pr
ivate
sanitizePath
(
p
)
{
const
caseAwarePath
=
platform
.
isWindows
||
platform
.
isMacintosh
?
workspacePath
.
toLowerCase
()
:
workspacePath
;
return
platform
.
isLinux
?
p
:
p
.
toLowerCase
()
;
const
workspaceHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
caseAwarePath
).
digest
(
'
hex
'
);
}
return
path
.
join
(
this
.
backupHome
,
workspaceHash
);
protected
getWorkspaceHash
(
workspacePath
:
string
):
string
{
return
crypto
.
createHash
(
'
md5
'
).
update
(
this
.
sanitizePath
(
workspacePath
)).
digest
(
'
hex
'
);
}
}
}
}
src/vs/platform/backup/test/electron-main/backupMainService.test.ts
浏览文件 @
d5349d2b
...
@@ -28,16 +28,24 @@ class TestBackupMainService extends BackupMainService {
...
@@ -28,16 +28,24 @@ class TestBackupMainService extends BackupMainService {
this
.
loadSync
();
this
.
loadSync
();
}
}
public
remove
WorkspaceBackupPathSync
(
workspace
:
Uri
):
void
{
public
remove
BackupPathSync
(
workspaceIdenfitier
:
string
,
isEmptyWorkspace
:
boolean
):
void
{
return
super
.
remove
WorkspaceBackupPathSync
(
w
orkspace
);
return
super
.
remove
BackupPathSync
(
workspaceIdenfitier
,
isEmptyW
orkspace
);
}
}
public
loadSync
():
void
{
public
loadSync
():
void
{
super
.
loadSync
();
super
.
loadSync
();
}
}
public
sanitizeFolderWorkspaces
(
backups
:
IBackupWorkspacesFormat
):
void
{
super
.
sanitizeFolderWorkspaces
(
backups
);
}
public
toBackupPath
(
workspacePath
:
string
):
string
{
public
toBackupPath
(
workspacePath
:
string
):
string
{
return
super
.
toBackupPath
(
workspacePath
);
return
path
.
join
(
this
.
backupHome
,
super
.
getWorkspaceHash
(
workspacePath
));
}
public
getWorkspaceHash
(
workspacePath
:
string
):
string
{
return
super
.
getWorkspaceHash
(
workspacePath
);
}
}
}
}
...
@@ -66,84 +74,20 @@ suite('BackupMainService', () => {
...
@@ -66,84 +74,20 @@ suite('BackupMainService', () => {
extfs
.
del
(
backupHome
,
os
.
tmpdir
(),
done
);
extfs
.
del
(
backupHome
,
os
.
tmpdir
(),
done
);
});
});
test
(
'
getWorkspaceBackupPaths should return [] when workspaces.json doesn
\'
t exist
'
,
()
=>
{
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
});
test
(
'
getWorkspaceBackupPaths should return [] when workspaces.json is not properly formed JSON
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
''
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{]
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
foo
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
});
test
(
'
getWorkspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is absent
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
});
test
(
'
getWorkspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is not a string array
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{}}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{"foo": ["bar"]}}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{"foo": []}}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{"foo": "bar"}}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":"foo"}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":1}
'
);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[]);
});
test
(
'
pushWorkspaceBackupPathsSync should persist paths to workspaces.json
'
,
()
=>
{
service
.
pushWorkspaceBackupPathsSync
([
fooFile
,
barFile
]);
assert
.
deepEqual
(
service
.
getWorkspaceBackupPaths
(),
[
fooFile
.
fsPath
,
barFile
.
fsPath
]);
});
test
(
'
removeWorkspaceBackupPath should remove workspaces from workspaces.json
'
,
done
=>
{
service
.
pushWorkspaceBackupPathsSync
([
fooFile
,
barFile
]);
service
.
removeWorkspaceBackupPathSync
(
fooFile
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
buffer
=>
{
const
json
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
buffer
);
assert
.
deepEqual
(
json
.
folderWorkspaces
,
[
barFile
.
fsPath
]);
service
.
removeWorkspaceBackupPathSync
(
barFile
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
content
=>
{
const
json2
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
content
);
assert
.
deepEqual
(
json2
.
folderWorkspaces
,
[]);
done
();
});
});
});
test
(
'
removeWorkspaceBackupPath should fail gracefully when removing a path that doesn
\'
t exist
'
,
done
=>
{
const
workspacesJson
:
IBackupWorkspacesFormat
=
{
folderWorkspaces
:
[
fooFile
.
fsPath
]
};
pfs
.
writeFile
(
backupWorkspacesPath
,
JSON
.
stringify
(
workspacesJson
)).
then
(()
=>
{
service
.
removeWorkspaceBackupPathSync
(
barFile
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
content
=>
{
const
json
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
content
);
assert
.
deepEqual
(
json
.
folderWorkspaces
,
[
fooFile
.
fsPath
]);
done
();
});
});
});
test
(
'
service validates backup workspaces on startup and cleans up
'
,
done
=>
{
test
(
'
service validates backup workspaces on startup and cleans up
'
,
done
=>
{
// 1) backup workspace path does not exist
// 1) backup workspace path does not exist
service
.
pushWorkspaceBackupPathsSync
([
fooFile
,
barFile
]);
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
2
,
false
,
null
,
barFile
.
fsPath
);
service
.
loadSync
();
service
.
loadSync
();
assert
.
equal
(
service
.
getWorkspaceBackupPaths
().
length
,
0
);
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]
);
// 2) backup workspace path exists with empty contents within
// 2) backup workspace path exists with empty contents within
fs
.
mkdirSync
(
service
.
toBackupPath
(
fooFile
.
fsPath
));
fs
.
mkdirSync
(
service
.
toBackupPath
(
fooFile
.
fsPath
));
fs
.
mkdirSync
(
service
.
toBackupPath
(
barFile
.
fsPath
));
fs
.
mkdirSync
(
service
.
toBackupPath
(
barFile
.
fsPath
));
service
.
pushWorkspaceBackupPathsSync
([
fooFile
,
barFile
]);
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
2
,
false
,
null
,
barFile
.
fsPath
);
service
.
loadSync
();
service
.
loadSync
();
assert
.
equal
(
service
.
getWorkspaceBackupPaths
().
length
,
0
);
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]
);
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
fooFile
.
fsPath
)));
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
fooFile
.
fsPath
)));
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
barFile
.
fsPath
)));
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
barFile
.
fsPath
)));
...
@@ -152,27 +96,230 @@ suite('BackupMainService', () => {
...
@@ -152,27 +96,230 @@ suite('BackupMainService', () => {
fs
.
mkdirSync
(
service
.
toBackupPath
(
barFile
.
fsPath
));
fs
.
mkdirSync
(
service
.
toBackupPath
(
barFile
.
fsPath
));
fs
.
mkdirSync
(
path
.
join
(
service
.
toBackupPath
(
fooFile
.
fsPath
),
'
file
'
));
fs
.
mkdirSync
(
path
.
join
(
service
.
toBackupPath
(
fooFile
.
fsPath
),
'
file
'
));
fs
.
mkdirSync
(
path
.
join
(
service
.
toBackupPath
(
barFile
.
fsPath
),
'
untitled
'
));
fs
.
mkdirSync
(
path
.
join
(
service
.
toBackupPath
(
barFile
.
fsPath
),
'
untitled
'
));
service
.
pushWorkspaceBackupPathsSync
([
fooFile
,
barFile
]);
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
2
,
false
,
null
,
barFile
.
fsPath
);
service
.
loadSync
();
service
.
loadSync
();
assert
.
equal
(
service
.
getWorkspaceBackupPaths
().
length
,
0
);
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]
);
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
fooFile
.
fsPath
)));
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
fooFile
.
fsPath
)));
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
barFile
.
fsPath
)));
assert
.
ok
(
!
fs
.
exists
(
service
.
toBackupPath
(
barFile
.
fsPath
)));
done
();
done
();
});
});
test
(
'
toBackupPath ignores case on Windows and Mac
'
,
()
=>
{
suite
(
'
loadSync
'
,
()
=>
{
// Skip test on Linux
test
(
'
workspaceBackupPaths should return [] when workspaces.json doesn
\'
t exist
'
,
()
=>
{
if
(
platform
.
isLinux
)
{
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
return
;
});
}
if
(
platform
.
isMacintosh
)
{
test
(
'
workspaceBackupPaths should return [] when workspaces.json is not properly formed JSON
'
,
()
=>
{
assert
.
equal
(
service
.
toBackupPath
(
'
/foo
'
),
service
.
toBackupPath
(
'
/FOO
'
));
fs
.
writeFileSync
(
backupWorkspacesPath
,
''
);
}
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{]
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
foo
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
});
test
(
'
workspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is absent
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
});
if
(
platform
.
isWindows
)
{
test
(
'
workspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is not a string array
'
,
()
=>
{
assert
.
equal
(
service
.
toBackupPath
(
'
c:
\\
foo
'
),
service
.
toBackupPath
(
'
C:
\\
FOO
'
));
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{}}
'
);
}
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{"foo": ["bar"]}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{"foo": []}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":{"foo": "bar"}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":"foo"}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"folderWorkspaces":1}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[]);
});
test
(
'
emptyWorkspaceBackupPaths should return [] when workspaces.json doesn
\'
t exist
'
,
()
=>
{
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
});
test
(
'
emptyWorkspaceBackupPaths should return [] when workspaces.json is not properly formed JSON
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
''
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{]
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
foo
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
});
test
(
'
emptyWorkspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is absent
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
});
test
(
'
emptyWorkspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is not a string array
'
,
()
=>
{
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"emptyWorkspaces":{}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"emptyWorkspaces":{"foo": ["bar"]}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"emptyWorkspaces":{"foo": []}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"emptyWorkspaces":{"foo": "bar"}}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"emptyWorkspaces":"foo"}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
fs
.
writeFileSync
(
backupWorkspacesPath
,
'
{"emptyWorkspaces":1}
'
);
service
.
loadSync
();
assert
.
deepEqual
(
service
.
emptyWorkspaceBackupPaths
,
[]);
});
});
suite
(
'
sanitizeFolderWorkspaces
'
,
()
=>
{
test
(
'
should merge same cased paths on Windows and Mac
'
,
()
=>
{
// Skip test on Linux
if
(
platform
.
isLinux
)
{
return
;
}
const
backups
:
IBackupWorkspacesFormat
=
{
folderWorkspaces
:
platform
.
isWindows
?
[
'
c:
\\
foo
'
,
'
C:
\\
FOO
'
,
'
c:
\\
FOO
'
]
:
[
'
/foo
'
,
'
/FOO
'
],
emptyWorkspaces
:
[]
};
service
.
sanitizeFolderWorkspaces
(
backups
);
if
(
platform
.
isWindows
)
{
assert
.
deepEqual
(
backups
.
folderWorkspaces
,
[
'
c:
\\
foo
'
]);
}
else
{
assert
.
deepEqual
(
backups
.
folderWorkspaces
,
[
'
/foo
'
]);
}
});
});
suite
(
'
registerWindowForBackups
'
,
()
=>
{
test
(
'
pushWorkspaceBackupPathsSync should persist paths to workspaces.json
'
,
()
=>
{
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
2
,
false
,
null
,
barFile
.
fsPath
);
assert
.
deepEqual
(
service
.
workspaceBackupPaths
,
[
fooFile
.
fsPath
,
barFile
.
fsPath
]);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
buffer
=>
{
const
json
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
buffer
);
assert
.
deepEqual
(
json
.
folderWorkspaces
,
[
fooFile
.
fsPath
,
barFile
.
fsPath
]);
});
});
});
suite
(
'
removeBackupPathSync
'
,
()
=>
{
test
(
'
should remove folder workspaces from workspaces.json
'
,
done
=>
{
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
2
,
false
,
null
,
barFile
.
fsPath
);
service
.
removeBackupPathSync
(
fooFile
.
fsPath
,
false
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
buffer
=>
{
const
json
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
buffer
);
assert
.
deepEqual
(
json
.
folderWorkspaces
,
[
barFile
.
fsPath
]);
service
.
removeBackupPathSync
(
barFile
.
fsPath
,
false
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
content
=>
{
const
json2
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
content
);
assert
.
deepEqual
(
json2
.
folderWorkspaces
,
[]);
done
();
});
});
});
test
(
'
should remove empty workspaces from workspaces.json
'
,
done
=>
{
service
.
registerWindowForBackups
(
1
,
true
,
'
foo
'
);
service
.
registerWindowForBackups
(
2
,
true
,
'
bar
'
);
service
.
removeBackupPathSync
(
'
foo
'
,
true
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
buffer
=>
{
const
json
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
buffer
);
assert
.
deepEqual
(
json
.
emptyWorkspaces
,
[
'
bar
'
]);
service
.
removeBackupPathSync
(
'
bar
'
,
true
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
content
=>
{
const
json2
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
content
);
assert
.
deepEqual
(
json2
.
emptyWorkspaces
,
[]);
done
();
});
});
});
test
(
'
should fail gracefully when removing a path that doesn
\'
t exist
'
,
done
=>
{
const
workspacesJson
:
IBackupWorkspacesFormat
=
{
folderWorkspaces
:
[
fooFile
.
fsPath
],
emptyWorkspaces
:
[]
};
pfs
.
writeFile
(
backupWorkspacesPath
,
JSON
.
stringify
(
workspacesJson
)).
then
(()
=>
{
service
.
removeBackupPathSync
(
barFile
.
fsPath
,
false
);
service
.
removeBackupPathSync
(
'
test
'
,
true
);
pfs
.
readFile
(
backupWorkspacesPath
,
'
utf-8
'
).
then
(
content
=>
{
const
json
=
<
IBackupWorkspacesFormat
>
JSON
.
parse
(
content
);
assert
.
deepEqual
(
json
.
folderWorkspaces
,
[
fooFile
.
fsPath
]);
done
();
});
});
});
});
suite
(
'
getWorkspaceHash
'
,
()
=>
{
test
(
'
should perform an md5 hash on the path
'
,
()
=>
{
assert
.
equal
(
service
.
getWorkspaceHash
(
'
/foo
'
),
'
1effb2475fcfba4f9e8b8a1dbc8f3caf
'
);
});
test
(
'
should ignore case on Windows and Mac
'
,
()
=>
{
// Skip test on Linux
if
(
platform
.
isLinux
)
{
return
;
}
if
(
platform
.
isMacintosh
)
{
assert
.
equal
(
service
.
getWorkspaceHash
(
'
/foo
'
),
service
.
getWorkspaceHash
(
'
/FOO
'
));
}
if
(
platform
.
isWindows
)
{
assert
.
equal
(
service
.
getWorkspaceHash
(
'
c:
\\
foo
'
),
service
.
getWorkspaceHash
(
'
C:
\\
FOO
'
));
}
});
});
suite
(
'
getBackupPath
'
,
()
=>
{
test
(
'
should return the window
\'
s correct path
'
,
done
=>
{
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
2
,
true
,
'
test
'
);
service
.
getBackupPath
(
1
).
then
(
window1Path
=>
{
assert
.
equal
(
window1Path
,
service
.
toBackupPath
(
fooFile
.
fsPath
));
service
.
getBackupPath
(
2
).
then
(
window2Path
=>
{
assert
.
equal
(
window2Path
,
path
.
join
(
backupHome
,
'
test
'
));
done
();
});
});
});
test
(
'
should override stale window paths with new paths
'
,
done
=>
{
service
.
registerWindowForBackups
(
1
,
false
,
null
,
fooFile
.
fsPath
);
service
.
registerWindowForBackups
(
1
,
false
,
null
,
barFile
.
fsPath
);
service
.
getBackupPath
(
1
).
then
(
windowPath
=>
{
assert
.
equal
(
windowPath
,
service
.
toBackupPath
(
barFile
.
fsPath
));
done
();
});
});
test
(
'
should throw when the window is not registered
'
,
()
=>
{
assert
.
throws
(()
=>
service
.
getBackupPath
(
1
));
});
});
});
});
});
\ No newline at end of file
src/vs/test/utils/servicesTestUtils.ts
浏览文件 @
d5349d2b
...
@@ -18,7 +18,7 @@ import { StorageService, InMemoryLocalStorage } from 'vs/workbench/services/stor
...
@@ -18,7 +18,7 @@ import { StorageService, InMemoryLocalStorage } from 'vs/workbench/services/stor
import
{
IEditorGroup
,
ConfirmResult
}
from
'
vs/workbench/common/editor
'
;
import
{
IEditorGroup
,
ConfirmResult
}
from
'
vs/workbench/common/editor
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
Severity
from
'
vs/base/common/severity
'
;
import
Severity
from
'
vs/base/common/severity
'
;
import
{
IBackupService
,
IBackupFileService
,
IBackupResult
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
,
IBackupFileService
,
IBackupResult
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
IQuickOpenService
}
from
'
vs/workbench/services/quickopen/common/quickOpenService
'
;
import
{
IQuickOpenService
}
from
'
vs/workbench/services/quickopen/common/quickOpenService
'
;
...
@@ -116,7 +116,7 @@ export class TestTextFileService extends TextFileService {
...
@@ -116,7 +116,7 @@ export class TestTextFileService extends TextFileService {
@
IFileService
fileService
:
IFileService
,
@
IFileService
fileService
:
IFileService
,
@
IUntitledEditorService
untitledEditorService
:
IUntitledEditorService
,
@
IUntitledEditorService
untitledEditorService
:
IUntitledEditorService
,
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
IBackup
Service
backupService
:
IBackup
Service
,
@
IBackup
ModelService
backupService
:
IBackupModel
Service
,
@
IMessageService
messageService
:
IMessageService
@
IMessageService
messageService
:
IMessageService
)
{
)
{
super
(
lifecycleService
,
contextService
,
configurationService
,
telemetryService
,
editorGroupService
,
fileService
,
untitledEditorService
,
instantiationService
,
backupService
,
messageService
);
super
(
lifecycleService
,
contextService
,
configurationService
,
telemetryService
,
editorGroupService
,
fileService
,
untitledEditorService
,
instantiationService
,
backupService
,
messageService
);
...
@@ -181,7 +181,7 @@ export function workbenchInstantiationService(): IInstantiationService {
...
@@ -181,7 +181,7 @@ export function workbenchInstantiationService(): IInstantiationService {
instantiationService
.
stub
(
IModelService
,
createMockModelService
(
instantiationService
));
instantiationService
.
stub
(
IModelService
,
createMockModelService
(
instantiationService
));
instantiationService
.
stub
(
IFileService
,
TestFileService
);
instantiationService
.
stub
(
IFileService
,
TestFileService
);
instantiationService
.
stub
(
IBackupFileService
,
new
TestBackupFileService
());
instantiationService
.
stub
(
IBackupFileService
,
new
TestBackupFileService
());
instantiationService
.
stub
(
IBackupService
,
new
TestBackupService
());
instantiationService
.
stub
(
IBackup
Model
Service
,
new
TestBackupService
());
instantiationService
.
stub
(
ITelemetryService
,
NullTelemetryService
);
instantiationService
.
stub
(
ITelemetryService
,
NullTelemetryService
);
instantiationService
.
stub
(
IMessageService
,
new
TestMessageService
());
instantiationService
.
stub
(
IMessageService
,
new
TestMessageService
());
instantiationService
.
stub
(
IUntitledEditorService
,
instantiationService
.
createInstance
(
UntitledEditorService
));
instantiationService
.
stub
(
IUntitledEditorService
,
instantiationService
.
createInstance
(
UntitledEditorService
));
...
@@ -623,7 +623,7 @@ export const TestFileService = {
...
@@ -623,7 +623,7 @@ export const TestFileService = {
}
}
};
};
export
class
TestBackupService
implements
IBackupService
{
export
class
TestBackupService
implements
IBackup
Model
Service
{
public
_serviceBrand
:
any
;
public
_serviceBrand
:
any
;
public
isHotExitEnabled
:
boolean
=
false
;
public
isHotExitEnabled
:
boolean
=
false
;
...
...
src/vs/workbench/electron-browser/main.ts
浏览文件 @
d5349d2b
...
@@ -48,7 +48,6 @@ export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest {
...
@@ -48,7 +48,6 @@ export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest {
}
}
export
function
startup
(
configuration
:
IWindowConfiguration
):
TPromise
<
void
>
{
export
function
startup
(
configuration
:
IWindowConfiguration
):
TPromise
<
void
>
{
// Ensure others can listen to zoom level changes
// Ensure others can listen to zoom level changes
browser
.
setZoomFactor
(
webFrame
.
getZoomFactor
());
browser
.
setZoomFactor
(
webFrame
.
getZoomFactor
());
browser
.
setZoomLevel
(
webFrame
.
getZoomLevel
());
browser
.
setZoomLevel
(
webFrame
.
getZoomLevel
());
...
...
src/vs/workbench/electron-browser/shell.ts
浏览文件 @
d5349d2b
...
@@ -87,6 +87,8 @@ import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
...
@@ -87,6 +87,8 @@ import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import
{
IUpdateService
}
from
'
vs/platform/update/common/update
'
;
import
{
IUpdateService
}
from
'
vs/platform/update/common/update
'
;
import
{
URLChannelClient
}
from
'
vs/platform/url/common/urlIpc
'
;
import
{
URLChannelClient
}
from
'
vs/platform/url/common/urlIpc
'
;
import
{
IURLService
}
from
'
vs/platform/url/common/url
'
;
import
{
IURLService
}
from
'
vs/platform/url/common/url
'
;
import
{
IBackupService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
BackupChannelClient
}
from
'
vs/platform/backup/common/backupIpc
'
;
import
{
ReloadWindowAction
}
from
'
vs/workbench/electron-browser/actions
'
;
import
{
ReloadWindowAction
}
from
'
vs/workbench/electron-browser/actions
'
;
import
{
ExtensionHostProcessWorker
}
from
'
vs/workbench/electron-browser/extensionHost
'
;
import
{
ExtensionHostProcessWorker
}
from
'
vs/workbench/electron-browser/extensionHost
'
;
import
{
remote
}
from
'
electron
'
;
import
{
remote
}
from
'
electron
'
;
...
@@ -439,6 +441,10 @@ export class WorkbenchShell {
...
@@ -439,6 +441,10 @@ export class WorkbenchShell {
const
urlChannelClient
=
new
URLChannelClient
(
urlChannel
,
windowIPCService
.
getWindowId
());
const
urlChannelClient
=
new
URLChannelClient
(
urlChannel
,
windowIPCService
.
getWindowId
());
serviceCollection
.
set
(
IURLService
,
urlChannelClient
);
serviceCollection
.
set
(
IURLService
,
urlChannelClient
);
const
backupChannel
=
mainProcessClient
.
getChannel
(
'
backup
'
);
const
backupChannelClient
=
new
BackupChannelClient
(
backupChannel
);
serviceCollection
.
set
(
IBackupService
,
backupChannelClient
);
return
[
instantiationServiceImpl
,
serviceCollection
];
return
[
instantiationServiceImpl
,
serviceCollection
];
}
}
...
...
src/vs/workbench/electron-browser/workbench.ts
浏览文件 @
d5349d2b
...
@@ -19,9 +19,9 @@ import assert = require('vs/base/common/assert');
...
@@ -19,9 +19,9 @@ import assert = require('vs/base/common/assert');
import
timer
=
require
(
'
vs/base/common/timer
'
);
import
timer
=
require
(
'
vs/base/common/timer
'
);
import
{
StopWatch
}
from
'
vs/base/common/stopwatch
'
;
import
{
StopWatch
}
from
'
vs/base/common/stopwatch
'
;
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
{
Backup
Service
}
from
'
vs/workbench/services/backup/node/backup
Service
'
;
import
{
Backup
ModelService
}
from
'
vs/workbench/services/backup/node/backupModel
Service
'
;
import
{
BackupFileService
}
from
'
vs/workbench/services/backup/node/backupFileService
'
;
import
{
BackupFileService
}
from
'
vs/workbench/services/backup/node/backupFileService
'
;
import
{
IBackupService
,
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
,
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
toErrorMessage
}
from
'
vs/base/common/errorMessage
'
;
import
{
toErrorMessage
}
from
'
vs/base/common/errorMessage
'
;
import
{
Registry
}
from
'
vs/platform/platform
'
;
import
{
Registry
}
from
'
vs/platform/platform
'
;
import
{
isWindows
,
isLinux
,
isMacintosh
}
from
'
vs/base/common/platform
'
;
import
{
isWindows
,
isLinux
,
isMacintosh
}
from
'
vs/base/common/platform
'
;
...
@@ -458,10 +458,10 @@ export class Workbench implements IPartService {
...
@@ -458,10 +458,10 @@ export class Workbench implements IPartService {
// Backup File Service
// Backup File Service
const
workspace
=
this
.
contextService
.
getWorkspace
();
const
workspace
=
this
.
contextService
.
getWorkspace
();
serviceCollection
.
set
(
IBackupFileService
,
this
.
instantiationService
.
createInstance
(
BackupFileService
,
workspace
?
workspace
.
resource
:
null
));
serviceCollection
.
set
(
IBackupFileService
,
this
.
instantiationService
.
createInstance
(
BackupFileService
,
this
.
windowService
.
getCurrentWindowId
()
));
// Backup Service
// Backup Service
serviceCollection
.
set
(
IBackup
Service
,
this
.
instantiationService
.
createInstance
(
Backup
Service
));
serviceCollection
.
set
(
IBackup
ModelService
,
this
.
instantiationService
.
createInstance
(
BackupModel
Service
));
// Text File Service
// Text File Service
serviceCollection
.
set
(
ITextFileService
,
this
.
instantiationService
.
createInstance
(
TextFileService
));
serviceCollection
.
set
(
ITextFileService
,
this
.
instantiationService
.
createInstance
(
TextFileService
));
...
...
src/vs/workbench/parts/backup/common/backupModelTracker.ts
浏览文件 @
d5349d2b
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
import
Uri
from
'
vs/base/common/uri
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
{
IBackupService
,
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
,
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
ITextFileService
,
TextFileModelChangeEvent
,
StateChange
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
ITextFileService
,
TextFileModelChangeEvent
,
StateChange
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
...
@@ -24,7 +24,7 @@ export class BackupModelTracker implements IWorkbenchContribution {
...
@@ -24,7 +24,7 @@ export class BackupModelTracker implements IWorkbenchContribution {
constructor
(
constructor
(
@
IBackupFileService
private
backupFileService
:
IBackupFileService
,
@
IBackupFileService
private
backupFileService
:
IBackupFileService
,
@
IBackup
Service
private
backupService
:
IBackup
Service
,
@
IBackup
ModelService
private
backupService
:
IBackupModel
Service
,
@
IFileService
private
fileService
:
IFileService
,
@
IFileService
private
fileService
:
IFileService
,
@
ITextFileService
private
textFileService
:
ITextFileService
,
@
ITextFileService
private
textFileService
:
ITextFileService
,
@
IUntitledEditorService
private
untitledEditorService
:
IUntitledEditorService
,
@
IUntitledEditorService
private
untitledEditorService
:
IUntitledEditorService
,
...
...
src/vs/workbench/parts/backup/common/backupRestorer.ts
浏览文件 @
d5349d2b
...
@@ -12,7 +12,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
...
@@ -12,7 +12,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import
{
IWorkbenchContribution
}
from
'
vs/workbench/common/contributions
'
;
import
{
IWorkbenchContribution
}
from
'
vs/workbench/common/contributions
'
;
import
{
IPartService
}
from
'
vs/workbench/services/part/common/partService
'
;
import
{
IPartService
}
from
'
vs/workbench/services/part/common/partService
'
;
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
{
IBackupService
,
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
,
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
{
ITextModelResolverService
}
from
'
vs/editor/common/services/resolverService
'
;
import
{
ITextModelResolverService
}
from
'
vs/editor/common/services/resolverService
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
...
@@ -26,7 +26,7 @@ export class BackupRestorer implements IWorkbenchContribution {
...
@@ -26,7 +26,7 @@ export class BackupRestorer implements IWorkbenchContribution {
@
IUntitledEditorService
private
untitledEditorService
:
IUntitledEditorService
,
@
IUntitledEditorService
private
untitledEditorService
:
IUntitledEditorService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IPartService
private
partService
:
IPartService
,
@
IPartService
private
partService
:
IPartService
,
@
IBackup
Service
private
backupService
:
IBackup
Service
,
@
IBackup
ModelService
private
backupService
:
IBackupModel
Service
,
@
IWorkbenchEditorService
private
editorService
:
IWorkbenchEditorService
,
@
IWorkbenchEditorService
private
editorService
:
IWorkbenchEditorService
,
@
IBackupFileService
private
backupFileService
:
IBackupFileService
,
@
IBackupFileService
private
backupFileService
:
IBackupFileService
,
@
ITextModelResolverService
private
textModelResolverService
:
ITextModelResolverService
,
@
ITextModelResolverService
private
textModelResolverService
:
ITextModelResolverService
,
...
...
src/vs/workbench/services/backup/common/backup.ts
浏览文件 @
d5349d2b
...
@@ -12,7 +12,7 @@ import { ITextFileEditorModelManager, IRawTextContent } from 'vs/workbench/servi
...
@@ -12,7 +12,7 @@ import { ITextFileEditorModelManager, IRawTextContent } from 'vs/workbench/servi
import
{
IResolveContentOptions
,
IUpdateContentOptions
}
from
'
vs/platform/files/common/files
'
;
import
{
IResolveContentOptions
,
IUpdateContentOptions
}
from
'
vs/platform/files/common/files
'
;
import
{
ShutdownReason
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
import
{
ShutdownReason
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
export
const
IBackup
Service
=
createDecorator
<
IBackup
Service
>
(
'
backupService
'
);
export
const
IBackup
ModelService
=
createDecorator
<
IBackupModel
Service
>
(
'
backupService
'
);
export
const
IBackupFileService
=
createDecorator
<
IBackupFileService
>
(
'
backupFileService
'
);
export
const
IBackupFileService
=
createDecorator
<
IBackupFileService
>
(
'
backupFileService
'
);
export
const
BACKUP_FILE_RESOLVE_OPTIONS
:
IResolveContentOptions
=
{
acceptTextOnly
:
true
,
encoding
:
'
utf-8
'
};
export
const
BACKUP_FILE_RESOLVE_OPTIONS
:
IResolveContentOptions
=
{
acceptTextOnly
:
true
,
encoding
:
'
utf-8
'
};
...
@@ -26,7 +26,7 @@ export interface IBackupResult {
...
@@ -26,7 +26,7 @@ export interface IBackupResult {
* A service that handles the lifecycle of backups, eg. listening for file changes and acting
* A service that handles the lifecycle of backups, eg. listening for file changes and acting
* appropriately on shutdown.
* appropriately on shutdown.
*/
*/
export
interface
IBackupService
{
export
interface
IBackup
Model
Service
{
_serviceBrand
:
any
;
_serviceBrand
:
any
;
isHotExitEnabled
:
boolean
;
isHotExitEnabled
:
boolean
;
...
...
src/vs/workbench/services/backup/node/backupFileService.ts
浏览文件 @
d5349d2b
...
@@ -11,6 +11,7 @@ import pfs = require('vs/base/node/pfs');
...
@@ -11,6 +11,7 @@ import pfs = require('vs/base/node/pfs');
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
IBackupFileService
,
BACKUP_FILE_UPDATE_OPTIONS
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackupFileService
,
BACKUP_FILE_UPDATE_OPTIONS
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackupService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
...
@@ -86,39 +87,34 @@ export class BackupFileService implements IBackupFileService {
...
@@ -86,39 +87,34 @@ export class BackupFileService implements IBackupFileService {
private
static
readonly
META_MARKER
=
'
\n
'
;
private
static
readonly
META_MARKER
=
'
\n
'
;
protected
backupHome
:
string
;
protected
workspacesJsonPath
:
string
;
private
backupWorkspacePath
:
string
;
private
backupWorkspacePath
:
string
;
private
ready
:
TPromise
<
IBackupFilesModel
>
;
private
ready
:
TPromise
<
IBackupFilesModel
>
;
constructor
(
constructor
(
private
currentWorkspace
:
Uri
,
windowId
:
number
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IFileService
private
fileService
:
IFileService
@
IFileService
private
fileService
:
IFileService
,
@
IBackupService
private
backupService
:
IBackupService
)
{
)
{
this
.
backupHome
=
environmentService
.
backupHome
;
this
.
ready
=
this
.
init
(
windowId
);
this
.
workspacesJsonPath
=
environmentService
.
backupWorkspacesPath
;
if
(
this
.
currentWorkspace
)
{
this
.
backupWorkspacePath
=
path
.
join
(
this
.
backupHome
,
this
.
hashPath
(
this
.
currentWorkspace
));
}
this
.
ready
=
this
.
init
();
}
}
private
get
backupEnabled
():
boolean
{
private
get
backupEnabled
():
boolean
{
return
this
.
currentWorkspace
&&
!
this
.
environmentService
.
isExtensionDevelopment
;
// Hot exit is disabled for empty workspaces and when doing extension development
// Hot exit is disabled when doing extension development
return
!
this
.
environmentService
.
isExtensionDevelopment
;
}
}
private
init
():
TPromise
<
IBackupFilesModel
>
{
private
init
(
windowId
:
number
):
TPromise
<
IBackupFilesModel
>
{
const
model
=
new
BackupFilesModel
();
const
model
=
new
BackupFilesModel
();
if
(
!
this
.
backupEnabled
)
{
if
(
!
this
.
backupEnabled
)
{
return
TPromise
.
as
(
model
);
return
TPromise
.
as
(
model
);
}
}
return
model
.
resolve
(
this
.
backupWorkspacePath
);
return
this
.
backupService
.
getBackupPath
(
windowId
).
then
(
backupPath
=>
{
this
.
backupWorkspacePath
=
backupPath
;
return
model
.
resolve
(
this
.
backupWorkspacePath
);
});
}
}
public
hasBackup
(
resource
:
Uri
):
TPromise
<
boolean
>
{
public
hasBackup
(
resource
:
Uri
):
TPromise
<
boolean
>
{
...
...
src/vs/workbench/services/backup/node/backupService.ts
→
src/vs/workbench/services/backup/node/backup
Model
Service.ts
浏览文件 @
d5349d2b
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
import
platform
=
require
(
'
vs/base/common/platform
'
);
import
platform
=
require
(
'
vs/base/common/platform
'
);
import
Uri
from
'
vs/base/common/uri
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
IBackupService
,
IBackupFileService
,
IBackupResult
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
,
IBackupFileService
,
IBackupResult
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
ITextFileEditorModel
,
ITextFileEditorModelManager
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
ITextFileEditorModel
,
ITextFileEditorModelManager
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
...
@@ -19,7 +19,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
...
@@ -19,7 +19,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import
{
IWindowsService
}
from
'
vs/platform/windows/common/windows
'
;
import
{
IWindowsService
}
from
'
vs/platform/windows/common/windows
'
;
import
{
ShutdownReason
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
import
{
ShutdownReason
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
export
class
Backup
Service
implements
IBackup
Service
{
export
class
Backup
ModelService
implements
IBackupModel
Service
{
public
_serviceBrand
:
any
;
public
_serviceBrand
:
any
;
...
@@ -49,8 +49,7 @@ export class BackupService implements IBackupService {
...
@@ -49,8 +49,7 @@ export class BackupService implements IBackupService {
}
}
private
onConfigurationChange
(
configuration
:
IFilesConfiguration
):
void
{
private
onConfigurationChange
(
configuration
:
IFilesConfiguration
):
void
{
// Hot exit is disabled for empty workspaces
this
.
configuredHotExit
=
configuration
&&
configuration
.
files
&&
configuration
.
files
.
hotExit
;
this
.
configuredHotExit
=
this
.
contextService
.
getWorkspace
()
&&
configuration
&&
configuration
.
files
&&
configuration
.
files
.
hotExit
;
}
}
/**
/**
...
@@ -91,9 +90,7 @@ export class BackupService implements IBackupService {
...
@@ -91,9 +90,7 @@ export class BackupService implements IBackupService {
}
}
public
get
isHotExitEnabled
():
boolean
{
public
get
isHotExitEnabled
():
boolean
{
// If hot exit is enabled then save the dirty files in the workspace and then exit
return
!
this
.
environmentService
.
isExtensionDevelopment
&&
this
.
configuredHotExit
;
// Hot exit is currently disabled for empty workspaces (#13733).
return
!
this
.
environmentService
.
isExtensionDevelopment
&&
this
.
configuredHotExit
&&
!!
this
.
contextService
.
getWorkspace
();
}
}
public
backupBeforeShutdown
(
dirtyToBackup
:
Uri
[],
textFileEditorModelManager
:
ITextFileEditorModelManager
,
reason
:
ShutdownReason
):
TPromise
<
IBackupResult
>
{
public
backupBeforeShutdown
(
dirtyToBackup
:
Uri
[],
textFileEditorModelManager
:
ITextFileEditorModelManager
,
reason
:
ShutdownReason
):
TPromise
<
IBackupResult
>
{
...
@@ -141,11 +138,6 @@ export class BackupService implements IBackupService {
...
@@ -141,11 +138,6 @@ export class BackupService implements IBackupService {
return
TPromise
.
as
(
void
0
);
return
TPromise
.
as
(
void
0
);
}
}
const
workspace
=
this
.
contextService
.
getWorkspace
();
if
(
!
workspace
)
{
return
TPromise
.
as
(
void
0
);
// no backups to cleanup
}
return
this
.
backupFileService
.
discardAllWorkspaceBackups
();
return
this
.
backupFileService
.
discardAllWorkspaceBackups
();
}
}
...
...
src/vs/workbench/services/backup/test/backupFileService.test.ts
浏览文件 @
d5349d2b
...
@@ -17,9 +17,11 @@ import Uri from 'vs/base/common/uri';
...
@@ -17,9 +17,11 @@ import Uri from 'vs/base/common/uri';
import
{
BackupFileService
,
BackupFilesModel
}
from
'
vs/workbench/services/backup/node/backupFileService
'
;
import
{
BackupFileService
,
BackupFilesModel
}
from
'
vs/workbench/services/backup/node/backupFileService
'
;
import
{
FileService
}
from
'
vs/workbench/services/files/node/fileService
'
;
import
{
FileService
}
from
'
vs/workbench/services/files/node/fileService
'
;
import
{
EnvironmentService
}
from
'
vs/platform/environment/node/environmentService
'
;
import
{
EnvironmentService
}
from
'
vs/platform/environment/node/environmentService
'
;
import
{
IBackupService
}
from
'
vs/platform/backup/common/backup
'
;
import
{
parseArgs
}
from
'
vs/platform/environment/node/argv
'
;
import
{
parseArgs
}
from
'
vs/platform/environment/node/argv
'
;
import
{
TextModel
}
from
'
vs/editor/common/model/textModel
'
;
import
{
TextModel
}
from
'
vs/editor/common/model/textModel
'
;
import
{
IRawTextContent
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IRawTextContent
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
class
TestEnvironmentService
extends
EnvironmentService
{
class
TestEnvironmentService
extends
EnvironmentService
{
...
@@ -32,19 +34,6 @@ class TestEnvironmentService extends EnvironmentService {
...
@@ -32,19 +34,6 @@ class TestEnvironmentService extends EnvironmentService {
get
backupWorkspacesPath
():
string
{
return
this
.
_backupWorkspacesPath
;
}
get
backupWorkspacesPath
():
string
{
return
this
.
_backupWorkspacesPath
;
}
}
}
class
TestBackupFileService
extends
BackupFileService
{
constructor
(
workspace
:
Uri
,
backupHome
:
string
,
workspacesJsonPath
:
string
)
{
const
fileService
=
new
FileService
(
workspace
.
fsPath
,
{
disableWatcher
:
true
},
null
);
const
testEnvironmentService
=
new
TestEnvironmentService
(
backupHome
,
workspacesJsonPath
);
super
(
workspace
,
testEnvironmentService
,
fileService
);
}
public
getBackupResource
(
resource
:
Uri
):
Uri
{
return
super
.
getBackupResource
(
resource
);
}
}
const
parentDir
=
path
.
join
(
os
.
tmpdir
(),
'
vsctests
'
,
'
service
'
);
const
parentDir
=
path
.
join
(
os
.
tmpdir
(),
'
vsctests
'
,
'
service
'
);
const
backupHome
=
path
.
join
(
parentDir
,
'
Backups
'
);
const
backupHome
=
path
.
join
(
parentDir
,
'
Backups
'
);
const
workspacesJsonPath
=
path
.
join
(
backupHome
,
'
workspaces.json
'
);
const
workspacesJsonPath
=
path
.
join
(
backupHome
,
'
workspaces.json
'
);
...
@@ -58,6 +47,23 @@ const fooBackupPath = path.join(workspaceBackupPath, 'file', crypto.createHash('
...
@@ -58,6 +47,23 @@ const fooBackupPath = path.join(workspaceBackupPath, 'file', crypto.createHash('
const
barBackupPath
=
path
.
join
(
workspaceBackupPath
,
'
file
'
,
crypto
.
createHash
(
'
md5
'
).
update
(
barFile
.
fsPath
).
digest
(
'
hex
'
));
const
barBackupPath
=
path
.
join
(
workspaceBackupPath
,
'
file
'
,
crypto
.
createHash
(
'
md5
'
).
update
(
barFile
.
fsPath
).
digest
(
'
hex
'
));
const
untitledBackupPath
=
path
.
join
(
workspaceBackupPath
,
'
untitled
'
,
crypto
.
createHash
(
'
md5
'
).
update
(
platform
.
isLinux
?
untitledFile
.
fsPath
:
untitledFile
.
fsPath
.
toLowerCase
()).
digest
(
'
hex
'
));
const
untitledBackupPath
=
path
.
join
(
workspaceBackupPath
,
'
untitled
'
,
crypto
.
createHash
(
'
md5
'
).
update
(
platform
.
isLinux
?
untitledFile
.
fsPath
:
untitledFile
.
fsPath
.
toLowerCase
()).
digest
(
'
hex
'
));
class
TestBackupFileService
extends
BackupFileService
{
constructor
(
workspace
:
Uri
,
backupHome
:
string
,
workspacesJsonPath
:
string
)
{
const
fileService
=
new
FileService
(
workspace
.
fsPath
,
{
disableWatcher
:
true
},
null
);
const
environmentService
=
new
TestEnvironmentService
(
backupHome
,
workspacesJsonPath
);
const
backupService
:
IBackupService
=
{
_serviceBrand
:
null
,
getBackupPath
:
()
=>
TPromise
.
as
(
workspaceBackupPath
)
};
super
(
1
,
environmentService
,
fileService
,
backupService
);
}
public
getBackupResource
(
resource
:
Uri
):
Uri
{
return
super
.
getBackupResource
(
resource
);
}
}
suite
(
'
BackupFileService
'
,
()
=>
{
suite
(
'
BackupFileService
'
,
()
=>
{
let
service
:
TestBackupFileService
;
let
service
:
TestBackupFileService
;
...
@@ -78,159 +84,173 @@ suite('BackupFileService', () => {
...
@@ -78,159 +84,173 @@ suite('BackupFileService', () => {
extfs
.
del
(
backupHome
,
os
.
tmpdir
(),
done
);
extfs
.
del
(
backupHome
,
os
.
tmpdir
(),
done
);
});
});
test
(
'
getBackupResource should get the correct backup path for text files
'
,
()
=>
{
suite
(
'
getBackupResource
'
,
()
=>
{
// Format should be: <backupHome>/<workspaceHash>/<scheme>/<filePathHash>
test
(
'
should get the correct backup path for text files
'
,
()
=>
{
const
backupResource
=
fooFile
;
// Format should be: <backupHome>/<workspaceHash>/<scheme>/<filePathHash>
const
workspaceHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
workspaceResource
.
fsPath
).
digest
(
'
hex
'
);
const
backupResource
=
fooFile
;
const
filePathHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
backupResource
.
fsPath
).
digest
(
'
hex
'
);
const
workspaceHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
workspaceResource
.
fsPath
).
digest
(
'
hex
'
);
const
expectedPath
=
Uri
.
file
(
path
.
join
(
backupHome
,
workspaceHash
,
'
file
'
,
filePathHash
)).
fsPath
;
const
filePathHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
backupResource
.
fsPath
).
digest
(
'
hex
'
);
assert
.
equal
(
service
.
getBackupResource
(
backupResource
).
fsPath
,
expectedPath
);
const
expectedPath
=
Uri
.
file
(
path
.
join
(
backupHome
,
workspaceHash
,
'
file
'
,
filePathHash
)).
fsPath
;
});
assert
.
equal
(
service
.
getBackupResource
(
backupResource
).
fsPath
,
expectedPath
);
});
test
(
'
getBackupResource should get the correct backup path for untitled files
'
,
()
=>
{
// Format should be: <backupHome>/<workspaceHash>/<scheme>/<filePath>
const
backupResource
=
Uri
.
from
({
scheme
:
'
untitled
'
,
path
:
'
Untitled-1
'
});
const
workspaceHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
workspaceResource
.
fsPath
).
digest
(
'
hex
'
);
const
filePathHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
platform
.
isLinux
?
backupResource
.
fsPath
:
backupResource
.
fsPath
.
toLowerCase
()).
digest
(
'
hex
'
);
const
expectedPath
=
Uri
.
file
(
path
.
join
(
backupHome
,
workspaceHash
,
'
untitled
'
,
filePathHash
)).
fsPath
;
assert
.
equal
(
service
.
getBackupResource
(
backupResource
).
fsPath
,
expectedPath
);
});
test
(
'
getBackupResource should ignore case on Windows and Mac
'
,
()
=>
{
test
(
'
should get the correct backup path for untitled files
'
,
()
=>
{
// Skip test on Linux
// Format should be: <backupHome>/<workspaceHash>/<scheme>/<filePath>
if
(
platform
.
isLinux
)
{
const
backupResource
=
Uri
.
from
({
scheme
:
'
untitled
'
,
path
:
'
Untitled-1
'
});
return
;
const
workspaceHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
workspaceResource
.
fsPath
).
digest
(
'
hex
'
);
}
const
filePathHash
=
crypto
.
createHash
(
'
md5
'
).
update
(
platform
.
isLinux
?
backupResource
.
fsPath
:
backupResource
.
fsPath
.
toLowerCase
()).
digest
(
'
hex
'
);
const
expectedPath
=
Uri
.
file
(
path
.
join
(
backupHome
,
workspaceHash
,
'
untitled
'
,
filePathHash
)).
fsPath
;
assert
.
equal
(
service
.
getBackupResource
(
backupResource
).
fsPath
,
expectedPath
);
});
if
(
platform
.
isMacintosh
)
{
test
(
'
should ignore case on Windows and Mac
'
,
()
=>
{
assert
.
equal
(
service
.
getBackupResource
(
Uri
.
file
(
'
/foo
'
)).
fsPath
,
service
.
getBackupResource
(
Uri
.
file
(
'
/FOO
'
)).
fsPath
);
// Skip test on Linux
}
if
(
platform
.
isLinux
)
{
return
;
}
if
(
platform
.
isWindows
)
{
if
(
platform
.
isMacintosh
)
{
assert
.
equal
(
service
.
getBackupResource
(
Uri
.
file
(
'
c:
\\
foo
'
)).
fsPath
,
service
.
getBackupResource
(
Uri
.
file
(
'
C:
\\
FOO
'
)).
fsPath
);
assert
.
equal
(
service
.
getBackupResource
(
Uri
.
file
(
'
/foo
'
)).
fsPath
,
service
.
getBackupResource
(
Uri
.
file
(
'
/FOO
'
)).
fsPath
);
}
}
});
test
(
'
doesTextFileHaveBackup should return whether a backup resource exists
'
,
done
=>
{
if
(
platform
.
isWindows
)
{
pfs
.
mkdirp
(
path
.
dirname
(
fooBackupPath
)).
then
(()
=>
{
assert
.
equal
(
service
.
getBackupResource
(
Uri
.
file
(
'
c:
\\
foo
'
)).
fsPath
,
service
.
getBackupResource
(
Uri
.
file
(
'
C:
\\
FOO
'
)).
fsPath
);
fs
.
writeFileSync
(
fooBackupPath
,
'
foo
'
);
}
service
=
new
TestBackupFileService
(
workspaceResource
,
backupHome
,
workspacesJsonPath
);
service
.
hasBackup
(
fooFile
).
then
(
exists2
=>
{
assert
.
equal
(
exists2
,
true
);
done
();
});
});
});
});
});
test
(
'
backupResource - text file
'
,
function
(
done
:
()
=>
void
)
{
suite
(
'
hasBackup
'
,
()
=>
{
service
.
backupResource
(
fooFile
,
'
test
'
).
then
(()
=>
{
test
(
'
should return whether a backup resource exists
'
,
done
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
1
);
pfs
.
mkdirp
(
path
.
dirname
(
fooBackupPath
)).
then
(()
=>
{
assert
.
equal
(
fs
.
existsSync
(
fooBackupPath
),
true
);
fs
.
writeFileSync
(
fooBackupPath
,
'
foo
'
);
assert
.
equal
(
fs
.
readFileSync
(
fooBackupPath
),
`
${
fooFile
.
toString
()}
\ntest`
);
service
=
new
TestBackupFileService
(
workspaceResource
,
backupHome
,
workspacesJsonPath
);
done
();
service
.
hasBackup
(
fooFile
).
then
(
exists2
=>
{
});
assert
.
equal
(
exists2
,
true
);
});
done
();
});
test
(
'
backupResource - untitled file
'
,
function
(
done
:
()
=>
void
)
{
});
service
.
backupResource
(
untitledFile
,
'
test
'
).
then
(()
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
1
);
assert
.
equal
(
fs
.
existsSync
(
untitledBackupPath
),
true
);
assert
.
equal
(
fs
.
readFileSync
(
untitledBackupPath
),
`
${
untitledFile
.
toString
()}
\ntest`
);
done
();
});
});
});
});
test
(
'
discardResourceBackup - text file
'
,
function
(
done
:
()
=>
void
)
{
suite
(
'
backupResource
'
,
()
=>
{
service
.
backupResource
(
fooFile
,
'
test
'
).
then
(()
=>
{
test
(
'
text file
'
,
function
(
done
:
()
=>
void
)
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
1
);
service
.
backupResource
(
fooFile
,
'
test
'
).
then
(()
=>
{
service
.
discardResourceBackup
(
fooFile
).
then
(()
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
1
);
assert
.
equal
(
fs
.
existsSync
(
fooBackupPath
),
fals
e
);
assert
.
equal
(
fs
.
existsSync
(
fooBackupPath
),
tru
e
);
assert
.
equal
(
fs
.
read
dirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
0
);
assert
.
equal
(
fs
.
read
FileSync
(
fooBackupPath
),
`
${
fooFile
.
toString
()}
\ntest`
);
done
();
done
();
});
});
});
});
});
test
(
'
discardResourceBackup - untitled file
'
,
function
(
done
:
()
=>
void
)
{
test
(
'
untitled file
'
,
function
(
done
:
()
=>
void
)
{
service
.
backupResource
(
untitledFile
,
'
test
'
).
then
(()
=>
{
service
.
backupResource
(
untitledFile
,
'
test
'
).
then
(()
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
1
);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
1
);
service
.
discardResourceBackup
(
untitledFile
).
then
(()
=>
{
assert
.
equal
(
fs
.
existsSync
(
untitledBackupPath
),
true
);
assert
.
equal
(
fs
.
existsSync
(
untitledBackupPath
),
false
);
assert
.
equal
(
fs
.
readFileSync
(
untitledBackupPath
),
`
${
untitledFile
.
toString
()}
\ntest`
);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
0
);
done
();
done
();
});
});
});
});
});
});
test
(
'
discardAllWorkspaceBackups - text file
'
,
function
(
done
:
()
=>
void
)
{
suite
(
'
discardResourceBackup
'
,
()
=>
{
service
.
backupResource
(
fooFile
,
'
test
'
).
then
(()
=>
{
test
(
'
text file
'
,
function
(
done
:
()
=>
void
)
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
1
);
service
.
backupResource
(
fooFile
,
'
test
'
).
then
(()
=>
{
service
.
backupResource
(
barFile
,
'
test
'
).
then
(()
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
1
);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
2
);
service
.
discardResourceBackup
(
fooFile
).
then
(()
=>
{
service
.
discardAllWorkspaceBackups
().
then
(()
=>
{
assert
.
equal
(
fs
.
existsSync
(
fooBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
fooBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
barBackupPath
),
false
);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
0
);
assert
.
equal
(
fs
.
existsSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)),
false
);
done
();
done
();
});
});
});
});
});
});
});
test
(
'
discardAllWorkspaceBackups - untitled file
'
,
function
(
done
:
()
=>
void
)
{
test
(
'
untitled file
'
,
function
(
done
:
()
=>
void
)
{
service
.
backupResource
(
untitledFile
,
'
test
'
).
then
(()
=>
{
service
.
backupResource
(
untitledFile
,
'
test
'
).
then
(()
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
1
);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
1
);
service
.
discardAllWorkspaceBackups
().
then
(()
=>
{
service
.
discardResourceBackup
(
untitledFile
).
then
(()
=>
{
assert
.
equal
(
fs
.
existsSync
(
untitledBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
untitledBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)),
false
);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
0
);
done
();
done
();
});
});
});
});
});
});
});
test
(
'
getWorkspaceFileBackups("file") - text file
'
,
done
=>
{
suite
(
'
discardAllWorkspaceBackups
'
,
()
=>
{
service
.
backupResource
(
fooFile
,
`test`
).
then
(()
=>
{
test
(
'
text file
'
,
function
(
done
:
()
=>
void
)
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
service
.
backupResource
(
fooFile
,
'
test
'
).
then
(()
=>
{
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
fooFile
.
fsPath
]);
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
1
);
service
.
backupResource
(
barFile
,
`test`
).
then
(()
=>
{
service
.
backupResource
(
barFile
,
'
test
'
).
then
(()
=>
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)).
length
,
2
);
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
fooFile
.
fsPath
,
barFile
.
fsPath
]);
service
.
discardAllWorkspaceBackups
().
then
(()
=>
{
assert
.
equal
(
fs
.
existsSync
(
fooBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
barBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
path
.
join
(
workspaceBackupPath
,
'
file
'
)),
false
);
done
();
done
();
});
});
});
});
});
});
});
});
});
test
(
'
getWorkspaceFileBackups("file") - untitled file
'
,
done
=>
{
test
(
'
untitled file
'
,
function
(
done
:
()
=>
void
)
{
service
.
backupResource
(
untitledFile
,
`test`
).
then
(()
=>
{
service
.
backupResource
(
untitledFile
,
'
test
'
).
then
(()
=>
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
assert
.
equal
(
fs
.
readdirSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)).
length
,
1
);
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
untitledFile
.
fsPath
]);
service
.
discardAllWorkspaceBackups
().
then
(()
=>
{
done
();
assert
.
equal
(
fs
.
existsSync
(
untitledBackupPath
),
false
);
assert
.
equal
(
fs
.
existsSync
(
path
.
join
(
workspaceBackupPath
,
'
untitled
'
)),
false
);
done
();
});
});
});
});
});
});
});
test
(
'
getWorkspaceFileBackups("untitled") - untitled file
'
,
done
=>
{
suite
(
'
getWorkspaceFileBackups
'
,
()
=>
{
service
.
backupResource
(
untitledFile
,
`test`
).
then
(()
=>
{
test
(
'
("file") - text file
'
,
done
=>
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
service
.
backupResource
(
fooFile
,
`test`
).
then
(()
=>
{
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
'
Untitled-1
'
]);
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
done
();
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
fooFile
.
fsPath
]);
service
.
backupResource
(
barFile
,
`test`
).
then
(()
=>
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
fooFile
.
fsPath
,
barFile
.
fsPath
]);
done
();
});
});
});
});
});
test
(
'
("file") - untitled file
'
,
done
=>
{
service
.
backupResource
(
untitledFile
,
`test`
).
then
(()
=>
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
untitledFile
.
fsPath
]);
done
();
});
});
});
test
(
'
("untitled") - untitled file
'
,
done
=>
{
service
.
backupResource
(
untitledFile
,
`test`
).
then
(()
=>
{
service
.
getWorkspaceFileBackups
().
then
(
textFiles
=>
{
assert
.
deepEqual
(
textFiles
.
map
(
f
=>
f
.
fsPath
),
[
'
Untitled-1
'
]);
done
();
});
});
});
});
});
});
});
test
(
'
parseBackupContent
'
,
()
=>
{
test
(
'
parseBackupContent
'
,
()
=>
{
const
rawTextContent
:
IRawTextContent
=
{
test
(
'
should separate metadata from content
'
,
()
=>
{
resource
:
null
,
const
rawTextContent
:
IRawTextContent
=
{
name
:
null
,
resource
:
null
,
mtime
:
null
,
name
:
null
,
etag
:
null
,
mtime
:
null
,
encoding
:
null
,
etag
:
null
,
value
:
TextModel
.
toRawText
(
'
metadata
\n
content
'
,
TextModel
.
DEFAULT_CREATION_OPTIONS
),
encoding
:
null
,
valueLogicalHash
:
null
value
:
TextModel
.
toRawText
(
'
metadata
\n
content
'
,
TextModel
.
DEFAULT_CREATION_OPTIONS
),
};
valueLogicalHash
:
null
assert
.
equal
(
service
.
parseBackupContent
(
rawTextContent
),
'
content
'
);
};
assert
.
equal
(
service
.
parseBackupContent
(
rawTextContent
),
'
content
'
);
});
});
});
});
});
...
...
src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts
浏览文件 @
d5349d2b
...
@@ -35,7 +35,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
...
@@ -35,7 +35,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import
{
IUntitledEditorService
}
from
'
vs/workbench/services/untitled/common/untitledEditorService
'
;
import
{
IUntitledEditorService
}
from
'
vs/workbench/services/untitled/common/untitledEditorService
'
;
import
{
ILifecycleService
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
import
{
ILifecycleService
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
IBackupService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IMessageService
}
from
'
vs/platform/message/common/message
'
;
import
{
IMessageService
}
from
'
vs/platform/message/common/message
'
;
class
SettingsTestEnvironmentService
extends
EnvironmentService
{
class
SettingsTestEnvironmentService
extends
EnvironmentService
{
...
@@ -60,7 +60,7 @@ class TestDirtyTextFileService extends TestTextFileService {
...
@@ -60,7 +60,7 @@ class TestDirtyTextFileService extends TestTextFileService {
@
IFileService
fileService
:
IFileService
,
@
IFileService
fileService
:
IFileService
,
@
IUntitledEditorService
untitledEditorService
:
IUntitledEditorService
,
@
IUntitledEditorService
untitledEditorService
:
IUntitledEditorService
,
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
IBackup
Service
backupService
:
IBackup
Service
,
@
IBackup
ModelService
backupService
:
IBackupModel
Service
,
@
IMessageService
messageService
:
IMessageService
@
IMessageService
messageService
:
IMessageService
)
{
)
{
super
(
lifecycleService
,
contextService
,
configurationService
,
telemetryService
,
editorService
,
editorGroupService
,
fileService
,
untitledEditorService
,
instantiationService
,
backupService
,
messageService
);
super
(
lifecycleService
,
contextService
,
configurationService
,
telemetryService
,
editorService
,
editorGroupService
,
fileService
,
untitledEditorService
,
instantiationService
,
backupService
,
messageService
);
...
...
src/vs/workbench/services/textfile/browser/textFileService.ts
浏览文件 @
d5349d2b
...
@@ -25,7 +25,7 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un
...
@@ -25,7 +25,7 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un
import
{
UntitledEditorModel
}
from
'
vs/workbench/common/editor/untitledEditorModel
'
;
import
{
UntitledEditorModel
}
from
'
vs/workbench/common/editor/untitledEditorModel
'
;
import
{
TextFileEditorModelManager
}
from
'
vs/workbench/services/textfile/common/textFileEditorModelManager
'
;
import
{
TextFileEditorModelManager
}
from
'
vs/workbench/services/textfile/common/textFileEditorModelManager
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IBackupService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IMessageService
,
Severity
}
from
'
vs/platform/message/common/message
'
;
import
{
IMessageService
,
Severity
}
from
'
vs/platform/message/common/message
'
;
/**
/**
...
@@ -57,7 +57,7 @@ export abstract class TextFileService implements ITextFileService {
...
@@ -57,7 +57,7 @@ export abstract class TextFileService implements ITextFileService {
@
IFileService
protected
fileService
:
IFileService
,
@
IFileService
protected
fileService
:
IFileService
,
@
IUntitledEditorService
private
untitledEditorService
:
IUntitledEditorService
,
@
IUntitledEditorService
private
untitledEditorService
:
IUntitledEditorService
,
@
IInstantiationService
private
instantiationService
:
IInstantiationService
,
@
IInstantiationService
private
instantiationService
:
IInstantiationService
,
@
IBackup
Service
private
backupService
:
IBackup
Service
,
@
IBackup
ModelService
private
backupService
:
IBackupModel
Service
,
@
IMessageService
private
messageService
:
IMessageService
@
IMessageService
private
messageService
:
IMessageService
)
{
)
{
this
.
toUnbind
=
[];
this
.
toUnbind
=
[];
...
...
src/vs/workbench/services/textfile/electron-browser/textFileService.ts
浏览文件 @
d5349d2b
...
@@ -28,7 +28,7 @@ import { ModelBuilder } from 'vs/editor/node/model/modelBuilder';
...
@@ -28,7 +28,7 @@ import { ModelBuilder } from 'vs/editor/node/model/modelBuilder';
import
product
from
'
vs/platform/product
'
;
import
product
from
'
vs/platform/product
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IBackupService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IBackup
Model
Service
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IMessageService
}
from
'
vs/platform/message/common/message
'
;
import
{
IMessageService
}
from
'
vs/platform/message/common/message
'
;
export
class
TextFileService
extends
AbstractTextFileService
{
export
class
TextFileService
extends
AbstractTextFileService
{
...
@@ -48,7 +48,7 @@ export class TextFileService extends AbstractTextFileService {
...
@@ -48,7 +48,7 @@ export class TextFileService extends AbstractTextFileService {
@
IWindowIPCService
private
windowService
:
IWindowIPCService
,
@
IWindowIPCService
private
windowService
:
IWindowIPCService
,
@
IModelService
private
modelService
:
IModelService
,
@
IModelService
private
modelService
:
IModelService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
IBackup
Service
backupService
:
IBackup
Service
,
@
IBackup
ModelService
backupService
:
IBackupModel
Service
,
@
IMessageService
messageService
:
IMessageService
@
IMessageService
messageService
:
IMessageService
)
{
)
{
super
(
lifecycleService
,
contextService
,
configurationService
,
telemetryService
,
editorGroupService
,
fileService
,
untitledEditorService
,
instantiationService
,
backupService
,
messageService
);
super
(
lifecycleService
,
contextService
,
configurationService
,
telemetryService
,
editorGroupService
,
fileService
,
untitledEditorService
,
instantiationService
,
backupService
,
messageService
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录