Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
1aaf1a80
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,发现更多精彩内容 >>
提交
1aaf1a80
编写于
11月 08, 2016
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'update'
上级
603e08d6
072c0aef
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
561 addition
and
168 deletion
+561
-168
src/vs/code/electron-main/main.ts
src/vs/code/electron-main/main.ts
+107
-73
src/vs/code/electron-main/menus.ts
src/vs/code/electron-main/menus.ts
+5
-7
src/vs/code/electron-main/windows.ts
src/vs/code/electron-main/windows.ts
+0
-34
src/vs/platform/update/common/update.ts
src/vs/platform/update/common/update.ts
+58
-0
src/vs/platform/update/common/updateIpc.ts
src/vs/platform/update/common/updateIpc.ts
+74
-0
src/vs/platform/update/electron-main/auto-updater.linux.ts
src/vs/platform/update/electron-main/auto-updater.linux.ts
+12
-5
src/vs/platform/update/electron-main/auto-updater.win32.ts
src/vs/platform/update/electron-main/auto-updater.win32.ts
+20
-22
src/vs/platform/update/electron-main/updateService.ts
src/vs/platform/update/electron-main/updateService.ts
+247
-0
src/vs/workbench/electron-browser/shell.ts
src/vs/workbench/electron-browser/shell.ts
+6
-0
src/vs/workbench/parts/update/electron-browser/update.ts
src/vs/workbench/parts/update/electron-browser/update.ts
+32
-27
未找到文件。
src/vs/code/electron-main/main.ts
浏览文件 @
1aaf1a80
...
...
@@ -20,7 +20,9 @@ import { WindowsService } from 'vs/platform/windows/electron-main/windowsService
import
{
WindowEventChannel
}
from
'
vs/code/common/windowsIpc
'
;
import
{
ILifecycleService
,
LifecycleService
}
from
'
vs/code/electron-main/lifecycle
'
;
import
{
VSCodeMenu
}
from
'
vs/code/electron-main/menus
'
;
import
{
IUpdateService
,
UpdateManager
}
from
'
vs/code/electron-main/update-manager
'
;
import
{
IUpdateService
}
from
'
vs/platform/update/common/update
'
;
import
{
UpdateChannel
}
from
'
vs/platform/update/common/updateIpc
'
;
import
{
UpdateService
}
from
'
vs/platform/update/electron-main/updateService
'
;
import
{
Server
as
ElectronIPCServer
}
from
'
vs/base/parts/ipc/electron-main/ipc.electron-main
'
;
import
{
Server
,
serve
,
connect
}
from
'
vs/base/parts/ipc/node/ipc.net
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
...
...
@@ -46,8 +48,13 @@ import { getPathLabel } from 'vs/base/common/labels';
import
{
IURLService
}
from
'
vs/platform/url/common/url
'
;
import
{
URLChannel
}
from
'
vs/platform/url/common/urlIpc
'
;
import
{
URLService
}
from
'
vs/platform/url/electron-main/urlService
'
;
import
{
ITelemetryService
,
NullTelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
ITelemetryAppenderChannel
,
TelemetryAppenderClient
}
from
'
vs/platform/telemetry/common/telemetryIpc
'
;
import
{
TelemetryService
,
ITelemetryServiceConfig
}
from
'
vs/platform/telemetry/common/telemetryService
'
;
import
{
resolveCommonProperties
}
from
'
vs/platform/telemetry/node/commonProperties
'
;
import
{
getDelayedChannel
}
from
'
vs/base/parts/ipc/common/ipc
'
;
import
product
from
'
vs/platform/product
'
;
import
pkg
from
'
vs/platform/package
'
;
import
*
as
fs
from
'
original-fs
'
;
import
*
as
cp
from
'
child_process
'
;
import
*
as
path
from
'
path
'
;
...
...
@@ -72,13 +79,13 @@ function quit(accessor: ServicesAccessor, arg?: any) {
process
.
exit
(
exitCode
);
// in main, process.exit === app.exit
}
// TODO@Joao wow this is huge, clean up!
function
main
(
accessor
:
ServicesAccessor
,
mainIpcServer
:
Server
,
userEnv
:
platform
.
IProcessEnvironment
):
void
{
const
instantiationService
=
accessor
.
get
(
IInstantiationService
);
const
logService
=
accessor
.
get
(
ILogService
);
const
environmentService
=
accessor
.
get
(
IEnvironmentService
);
const
windowsMainService
=
accessor
.
get
(
IWindowsMainService
);
const
lifecycleService
=
accessor
.
get
(
ILifecycleService
);
const
updateService
=
accessor
.
get
(
IUpdateService
);
const
configurationService
=
accessor
.
get
(
IConfigurationService
)
as
ConfigurationService
<
any
>
;
const
windowEventChannel
=
new
WindowEventChannel
(
windowsMainService
);
...
...
@@ -147,82 +154,107 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo
let
sharedProcessDisposable
;
spawnSharedProcess
(
initData
,
options
).
done
(
disposable
=>
{
const
sharedProcess
=
spawnSharedProcess
(
initData
,
options
).
then
(
disposable
=>
{
sharedProcessDisposable
=
disposable
;
connect
(
environmentService
.
sharedIPCHandle
,
'
main
'
)
.
done
(
client
=>
client
.
registerChannel
(
'
windowEvent
'
,
windowEventChannel
));
return
connect
(
environmentService
.
sharedIPCHandle
,
'
main
'
);
});
// Make sure we associate the program with the app user model id
// This will help Windows to associate the running program with
// any shortcut that is pinned to the taskbar and prevent showing
// two icons in the taskbar for the same app.
if
(
platform
.
isWindows
&&
product
.
win32AppUserModelId
)
{
app
.
setAppUserModelId
(
product
.
win32AppUserModelId
);
// Create a new service collection, because the telemetry service
// requires a connection to shared process, which was only established
// now.
const
services
=
new
ServiceCollection
();
services
.
set
(
IUpdateService
,
new
SyncDescriptor
(
UpdateService
));
if
(
environmentService
.
isBuilt
&&
!
environmentService
.
extensionDevelopmentPath
&&
!!
product
.
enableTelemetry
)
{
const
channel
=
getDelayedChannel
<
ITelemetryAppenderChannel
>
(
sharedProcess
.
then
(
c
=>
c
.
getChannel
(
'
telemetryAppender
'
)));
const
appender
=
new
TelemetryAppenderClient
(
channel
);
const
commonProperties
=
resolveCommonProperties
(
product
.
commit
,
pkg
.
version
);
const
piiPaths
=
[
environmentService
.
appRoot
,
environmentService
.
extensionsPath
];
const
config
:
ITelemetryServiceConfig
=
{
appender
,
commonProperties
,
piiPaths
};
services
.
set
(
ITelemetryService
,
new
SyncDescriptor
(
TelemetryService
,
config
));
}
else
{
services
.
set
(
ITelemetryService
,
NullTelemetryService
);
}
function
dispose
()
{
if
(
mainIpcServer
)
{
mainIpcServer
.
dispose
();
mainIpcServer
=
null
;
}
const
instantiationService2
=
instantiationService
.
createChild
(
services
);
if
(
sharedProcessDisposable
)
{
sharedProcessDisposable
.
dispose
();
}
instantiationService2
.
invokeFunction
(
accessor
=>
{
// Register more Electron IPC services
const
updateService
=
accessor
.
get
(
IUpdateService
);
const
updateChannel
=
new
UpdateChannel
(
updateService
);
electronIpcServer
.
registerChannel
(
'
update
'
,
updateChannel
);
// Register windowEvent
sharedProcess
.
done
(
client
=>
client
.
registerChannel
(
'
windowEvent
'
,
windowEventChannel
));
if
(
windowsMutex
)
{
windowsMutex
.
release
();
// Make sure we associate the program with the app user model id
// This will help Windows to associate the running program with
// any shortcut that is pinned to the taskbar and prevent showing
// two icons in the taskbar for the same app.
if
(
platform
.
isWindows
&&
product
.
win32AppUserModelId
)
{
app
.
setAppUserModelId
(
product
.
win32AppUserModelId
);
}
configurationService
.
dispose
();
}
function
dispose
()
{
if
(
mainIpcServer
)
{
mainIpcServer
.
dispose
();
mainIpcServer
=
null
;
}
// Dispose on app quit
app
.
on
(
'
will-quit
'
,
()
=>
{
logService
.
log
(
'
App#will-quit: disposing resources
'
);
if
(
sharedProcessDisposable
)
{
sharedProcessDisposable
.
dispose
();
}
dispose
();
});
if
(
windowsMutex
)
{
windowsMutex
.
release
();
}
// Dispose on vscode:exit
ipc
.
on
(
'
vscode:exit
'
,
(
event
,
code
:
number
)
=>
{
logService
.
log
(
'
IPC#vscode:exit
'
,
code
);
configurationService
.
dispose
();
}
dispose
();
process
.
exit
(
code
);
// in main, process.exit === app.exit
}
);
// Dispose on app quit
app
.
on
(
'
will-quit
'
,
()
=>
{
logService
.
log
(
'
App#will-quit: disposing resources
'
);
// Lifecycle
lifecycleService
.
ready
(
);
dispose
();
}
);
// Propagate to clients
windowsMainService
.
ready
(
userEnv
);
// Dispose on vscode:exit
ipc
.
on
(
'
vscode:exit
'
,
(
event
,
code
:
number
)
=>
{
logService
.
log
(
'
IPC#vscode:exit
'
,
code
);
// Install Menu
const
menu
=
instantiationService
.
createInstance
(
VSCodeMenu
);
menu
.
ready
(
);
dispose
();
process
.
exit
(
code
);
// in main, process.exit === app.exit
}
);
// Install JumpList on Windows (keep updated when windows open)
if
(
platform
.
isWindows
)
{
updateJumpList
(
windowsMainService
,
logService
);
windowsMainService
.
onOpen
(()
=>
updateJumpList
(
windowsMainService
,
logService
));
}
// Lifecycle
lifecycleService
.
ready
();
// Setup auto update
updateService
.
initialize
(
);
// Propagate to clients
windowsMainService
.
ready
(
userEnv
);
// Open our first window
if
(
environmentService
.
args
[
'
new-window
'
]
&&
environmentService
.
args
.
_
.
length
===
0
)
{
windowsMainService
.
open
({
cli
:
environmentService
.
args
,
forceNewWindow
:
true
,
forceEmpty
:
true
});
// new window if "-n" was used without paths
}
else
if
(
global
.
macOpenFiles
&&
global
.
macOpenFiles
.
length
&&
(
!
environmentService
.
args
.
_
||
!
environmentService
.
args
.
_
.
length
))
{
windowsMainService
.
open
({
cli
:
environmentService
.
args
,
pathsToOpen
:
global
.
macOpenFiles
});
// mac: open-file event received on startup
}
else
{
windowsMainService
.
open
({
cli
:
environmentService
.
args
,
forceNewWindow
:
environmentService
.
args
[
'
new-window
'
],
diffMode
:
environmentService
.
args
.
diff
});
// default: read paths from cli
}
// Install Menu
const
menu
=
instantiationService2
.
createInstance
(
VSCodeMenu
);
menu
.
ready
();
// Install JumpList on Windows (keep updated when windows open)
if
(
platform
.
isWindows
)
{
updateJumpList
(
windowsMainService
,
logService
);
windowsMainService
.
onOpen
(()
=>
updateJumpList
(
windowsMainService
,
logService
));
}
// Open our first window
if
(
environmentService
.
args
[
'
new-window
'
]
&&
environmentService
.
args
.
_
.
length
===
0
)
{
windowsMainService
.
open
({
cli
:
environmentService
.
args
,
forceNewWindow
:
true
,
forceEmpty
:
true
});
// new window if "-n" was used without paths
}
else
if
(
global
.
macOpenFiles
&&
global
.
macOpenFiles
.
length
&&
(
!
environmentService
.
args
.
_
||
!
environmentService
.
args
.
_
.
length
))
{
windowsMainService
.
open
({
cli
:
environmentService
.
args
,
pathsToOpen
:
global
.
macOpenFiles
});
// mac: open-file event received on startup
}
else
{
windowsMainService
.
open
({
cli
:
environmentService
.
args
,
forceNewWindow
:
environmentService
.
args
[
'
new-window
'
],
diffMode
:
environmentService
.
args
.
diff
});
// default: read paths from cli
}
});
}
// TODO@Joao TODO@Ben shouldn't this be inside windows service instead?
function
updateJumpList
(
windowsMainService
:
IWindowsMainService
,
logService
:
ILogService
):
void
{
const
jumpList
:
Electron
.
JumpListCategory
[]
=
[];
...
...
@@ -448,19 +480,7 @@ function createPaths(environmentService: IEnvironmentService): TPromise<any> {
return
TPromise
.
join
(
paths
.
map
(
p
=>
mkdirp
(
p
)))
as
TPromise
<
any
>
;
}
function
start
():
void
{
let
args
:
ParsedArgs
;
try
{
args
=
parseMainProcessArgv
(
process
.
argv
);
args
=
validatePaths
(
args
);
}
catch
(
err
)
{
console
.
error
(
err
.
message
);
process
.
exit
(
1
);
return
;
}
// TODO: isolate
function
createServices
(
args
):
IInstantiationService
{
const
services
=
new
ServiceCollection
();
services
.
set
(
IEnvironmentService
,
new
SyncDescriptor
(
EnvironmentService
,
args
,
process
.
execPath
));
...
...
@@ -471,10 +491,24 @@ function start(): void {
services
.
set
(
IStorageService
,
new
SyncDescriptor
(
StorageService
));
services
.
set
(
IConfigurationService
,
new
SyncDescriptor
(
ConfigurationService
));
services
.
set
(
IRequestService
,
new
SyncDescriptor
(
RequestService
));
services
.
set
(
IUpdateService
,
new
SyncDescriptor
(
UpdateManager
));
services
.
set
(
IURLService
,
new
SyncDescriptor
(
URLService
,
args
[
'
open-url
'
]));
const
instantiationService
=
new
InstantiationService
(
services
);
return
new
InstantiationService
(
services
);
}
function
start
():
void
{
let
args
:
ParsedArgs
;
try
{
args
=
parseMainProcessArgv
(
process
.
argv
);
args
=
validatePaths
(
args
);
}
catch
(
err
)
{
console
.
error
(
err
.
message
);
process
.
exit
(
1
);
return
;
}
const
instantiationService
=
createServices
(
args
);
// On some platforms we need to manually read from the global environment variables
// and assign them to the process environment (e.g. when doubleclick app on Mac)
...
...
src/vs/code/electron-main/menus.ts
浏览文件 @
1aaf1a80
...
...
@@ -15,7 +15,7 @@ import { IPath, VSCodeWindow } from 'vs/code/electron-main/window';
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IStorageService
}
from
'
vs/code/electron-main/storage
'
;
import
{
IFilesConfiguration
,
AutoSaveConfiguration
}
from
'
vs/platform/files/common/files
'
;
import
{
IUpdateService
,
State
as
UpdateState
}
from
'
vs/
code/electron-main/update-manager
'
;
import
{
IUpdateService
,
State
as
UpdateState
}
from
'
vs/
platform/update/common/update
'
;
import
{
Keybinding
}
from
'
vs/base/common/keybinding
'
;
import
product
from
'
vs/platform/product
'
;
...
...
@@ -125,7 +125,7 @@ export class VSCodeMenu {
this
.
configurationService
.
onDidUpdateConfiguration
(
e
=>
this
.
onConfigurationUpdated
(
e
.
config
,
true
/* update menu if changed */
));
// Listen to update service
this
.
updateService
.
on
(
'
change
'
,
()
=>
this
.
updateMenu
());
this
.
updateService
.
on
StateChange
(
()
=>
this
.
updateMenu
());
}
private
onConfigurationUpdated
(
config
:
IConfiguration
,
handleMenu
?:
boolean
):
void
{
...
...
@@ -751,11 +751,10 @@ export class VSCodeMenu {
return
[];
case
UpdateState
.
UpdateDownloaded
:
const
update
=
this
.
updateService
.
availableUpdate
;
return
[
new
MenuItem
({
label
:
nls
.
localize
(
'
miRestartToUpdate
'
,
"
Restart To Update...
"
),
click
:
()
=>
{
this
.
reportMenuActionTelemetry
(
'
RestartToUpdate
'
);
update
.
quitAndUpdate
();
this
.
updateService
.
quitAndInstall
();
}
})];
...
...
@@ -764,10 +763,9 @@ export class VSCodeMenu {
case
UpdateState
.
UpdateAvailable
:
if
(
platform
.
isLinux
)
{
const
update
=
this
.
updateService
.
availableUpdate
;
return
[
new
MenuItem
({
label
:
nls
.
localize
(
'
miDownloadUpdate
'
,
"
Download Available Update
"
),
click
:
()
=>
{
update
.
quitAndUpdate
();
this
.
updateService
.
quitAndInstall
();
}
})];
}
...
...
@@ -782,7 +780,7 @@ export class VSCodeMenu {
const
result
=
[
new
MenuItem
({
label
:
nls
.
localize
(
'
miCheckForUpdates
'
,
"
Check For Updates...
"
),
click
:
()
=>
setTimeout
(()
=>
{
this
.
reportMenuActionTelemetry
(
'
CheckForUpdate
'
);
this
.
updateService
.
checkForUpdates
(
true
);
this
.
updateService
.
checkForUpdates
(
true
)
.
done
(
null
,
err
=>
console
.
error
(
err
))
;
},
0
)
})];
...
...
src/vs/code/electron-main/windows.ts
浏览文件 @
1aaf1a80
...
...
@@ -22,7 +22,6 @@ import { ipcMain as ipc, app, screen, BrowserWindow, dialog } from 'electron';
import
{
IPathWithLineAndColumn
,
parseLineAndColumnAware
}
from
'
vs/code/electron-main/paths
'
;
import
{
ILifecycleService
}
from
'
vs/code/electron-main/lifecycle
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IUpdateService
,
IUpdate
}
from
'
vs/code/electron-main/update-manager
'
;
import
{
ILogService
}
from
'
vs/code/electron-main/log
'
;
import
{
IWindowEventService
}
from
'
vs/code/common/windows
'
;
import
{
createDecorator
,
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
...
...
@@ -153,7 +152,6 @@ export class WindowsManager implements IWindowsMainService, IWindowEventService
@
IStorageService
private
storageService
:
IStorageService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
,
@
ILifecycleService
private
lifecycleService
:
ILifecycleService
,
@
IUpdateService
private
updateService
:
IUpdateService
,
@
IConfigurationService
private
configurationService
:
IConfigurationService
)
{
}
...
...
@@ -250,38 +248,6 @@ export class WindowsManager implements IWindowsMainService, IWindowEventService
}
});
this
.
updateService
.
on
(
'
update-downloaded
'
,
(
update
:
IUpdate
)
=>
{
this
.
sendToFocused
(
'
vscode:telemetry
'
,
{
eventName
:
'
update:downloaded
'
,
data
:
{
version
:
update
.
version
}
});
this
.
sendToAll
(
'
vscode:update-downloaded
'
,
JSON
.
stringify
({
releaseNotes
:
update
.
releaseNotes
,
version
:
update
.
version
,
date
:
update
.
date
}));
});
ipc
.
on
(
'
vscode:update-apply
'
,
()
=>
{
this
.
logService
.
log
(
'
IPC#vscode:update-apply
'
);
if
(
this
.
updateService
.
availableUpdate
)
{
this
.
updateService
.
availableUpdate
.
quitAndUpdate
();
}
});
this
.
updateService
.
on
(
'
update-not-available
'
,
(
explicit
:
boolean
)
=>
{
this
.
sendToFocused
(
'
vscode:telemetry
'
,
{
eventName
:
'
update:notAvailable
'
,
data
:
{
explicit
}
});
if
(
explicit
)
{
this
.
sendToFocused
(
'
vscode:update-not-available
'
,
''
);
}
});
this
.
updateService
.
on
(
'
update-available
'
,
(
url
:
string
,
version
:
string
)
=>
{
if
(
url
)
{
this
.
sendToFocused
(
'
vscode:update-available
'
,
url
,
version
);
}
});
this
.
lifecycleService
.
onBeforeQuit
(()
=>
{
// 0-1 window open: Do not keep the list but just rely on the active window to be stored
...
...
src/vs/platform/update/common/update.ts
0 → 100644
浏览文件 @
1aaf1a80
/*---------------------------------------------------------------------------------------------
* 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
Event
from
'
vs/base/common/event
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
export
enum
State
{
Uninitialized
,
Idle
,
CheckingForUpdate
,
UpdateAvailable
,
UpdateDownloaded
}
export
enum
ExplicitState
{
Implicit
,
Explicit
}
export
interface
IRawUpdate
{
releaseNotes
:
string
;
version
:
string
;
date
:
Date
;
}
export
interface
IUpdate
{
version
:
string
;
date
?:
Date
;
releaseNotes
?:
string
;
url
?:
string
;
}
export
interface
IAutoUpdater
extends
NodeJS
.
EventEmitter
{
setFeedURL
(
url
:
string
):
void
;
checkForUpdates
():
void
;
quitAndInstall
():
void
;
}
export
const
IUpdateService
=
createDecorator
<
IUpdateService
>
(
'
updateService
'
);
export
interface
IUpdateService
{
_serviceBrand
:
any
;
readonly
onError
:
Event
<
any
>
;
readonly
onUpdateAvailable
:
Event
<
{
url
:
string
;
version
:
string
;
}
>
;
readonly
onUpdateNotAvailable
:
Event
<
boolean
>
;
readonly
onUpdateReady
:
Event
<
IRawUpdate
>
;
readonly
onStateChange
:
Event
<
State
>
;
readonly
state
:
State
;
checkForUpdates
(
explicit
:
boolean
):
TPromise
<
IUpdate
>
;
quitAndInstall
():
TPromise
<
void
>
;
}
\ No newline at end of file
src/vs/platform/update/common/updateIpc.ts
0 → 100644
浏览文件 @
1aaf1a80
/*---------------------------------------------------------------------------------------------
* 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
,
eventToCall
,
eventFromCall
}
from
'
vs/base/parts/ipc/common/ipc
'
;
import
Event
from
'
vs/base/common/event
'
;
import
{
IUpdateService
,
IRawUpdate
,
State
,
IUpdate
}
from
'
./update
'
;
export
interface
IUpdateChannel
extends
IChannel
{
call
(
command
:
'
event:onError
'
):
TPromise
<
void
>
;
call
(
command
:
'
event:onUpdateAvailable
'
):
TPromise
<
void
>
;
call
(
command
:
'
event:onUpdateNotAvailable
'
):
TPromise
<
void
>
;
call
(
command
:
'
event:onUpdateReady
'
):
TPromise
<
void
>
;
call
(
command
:
'
event:onStateChange
'
):
TPromise
<
void
>
;
call
(
command
:
'
checkForUpdates
'
,
arg
:
boolean
):
TPromise
<
IUpdate
>
;
call
(
command
:
'
quitAndInstall
'
):
TPromise
<
void
>
;
call
(
command
:
string
,
arg
?:
any
):
TPromise
<
any
>
;
}
export
class
UpdateChannel
implements
IUpdateChannel
{
constructor
(
private
service
:
IUpdateService
)
{
}
call
(
command
:
string
,
arg
?:
any
):
TPromise
<
any
>
{
switch
(
command
)
{
case
'
event:onError
'
:
return
eventToCall
(
this
.
service
.
onError
);
case
'
event:onUpdateAvailable
'
:
return
eventToCall
(
this
.
service
.
onUpdateAvailable
);
case
'
event:onUpdateNotAvailable
'
:
return
eventToCall
(
this
.
service
.
onUpdateNotAvailable
);
case
'
event:onUpdateReady
'
:
return
eventToCall
(
this
.
service
.
onUpdateReady
);
case
'
event:onStateChange
'
:
return
eventToCall
(
this
.
service
.
onStateChange
);
case
'
checkForUpdates
'
:
return
this
.
service
.
checkForUpdates
(
arg
);
case
'
quitAndInstall
'
:
return
this
.
service
.
quitAndInstall
();
}
}
}
export
class
UpdateChannelClient
implements
IUpdateService
{
_serviceBrand
:
any
;
private
_onError
=
eventFromCall
<
any
>
(
this
.
channel
,
'
event:onError
'
);
get
onError
():
Event
<
any
>
{
return
this
.
_onError
;
}
private
_onUpdateAvailable
=
eventFromCall
<
{
url
:
string
;
version
:
string
;
}
>
(
this
.
channel
,
'
event:onUpdateAvailable
'
);
get
onUpdateAvailable
():
Event
<
{
url
:
string
;
version
:
string
;
}
>
{
return
this
.
_onUpdateAvailable
;
}
private
_onUpdateNotAvailable
=
eventFromCall
<
boolean
>
(
this
.
channel
,
'
event:onUpdateNotAvailable
'
);
get
onUpdateNotAvailable
():
Event
<
boolean
>
{
return
this
.
_onUpdateNotAvailable
;
}
private
_onUpdateReady
=
eventFromCall
<
IRawUpdate
>
(
this
.
channel
,
'
event:onUpdateReady
'
);
get
onUpdateReady
():
Event
<
IRawUpdate
>
{
return
this
.
_onUpdateReady
;
}
private
_onStateChange
=
eventFromCall
<
State
>
(
this
.
channel
,
'
event:onStateChange
'
);
get
onStateChange
():
Event
<
State
>
{
return
this
.
_onStateChange
;
}
private
_state
:
State
=
State
.
Uninitialized
;
get
state
():
State
{
return
this
.
_state
;
};
constructor
(
private
channel
:
IChannel
)
{
this
.
onStateChange
(
state
=>
this
.
_state
=
state
);
}
checkForUpdates
(
explicit
:
boolean
):
TPromise
<
IUpdate
>
{
return
this
.
channel
.
call
(
'
checkForUpdates
'
,
explicit
);
}
quitAndInstall
():
TPromise
<
void
>
{
return
this
.
channel
.
call
(
'
quitAndInstall
'
);
}
}
\ No newline at end of file
src/vs/
cod
e/electron-main/auto-updater.linux.ts
→
src/vs/
platform/updat
e/electron-main/auto-updater.linux.ts
浏览文件 @
1aaf1a80
...
...
@@ -10,16 +10,19 @@ import { isString } from 'vs/base/common/types';
import
{
Promise
}
from
'
vs/base/common/winjs.base
'
;
import
{
asJson
}
from
'
vs/base/node/request
'
;
import
{
IRequestService
}
from
'
vs/platform/request/common/request
'
;
import
{
IAutoUpdater
}
from
'
vs/platform/update/common/update
'
;
import
product
from
'
vs/platform/product
'
;
export
interface
IUpdate
{
interface
IUpdate
{
url
:
string
;
name
:
string
;
releaseNotes
?:
string
;
version
?:
string
;
version
:
string
;
productVersion
:
string
;
hash
:
string
;
}
export
class
LinuxAutoUpdaterImpl
extends
EventEmitter
{
export
class
LinuxAutoUpdaterImpl
extends
EventEmitter
implements
IAutoUpdater
{
private
url
:
string
;
private
currentRequest
:
Promise
;
...
...
@@ -51,10 +54,10 @@ export class LinuxAutoUpdaterImpl extends EventEmitter {
this
.
currentRequest
=
this
.
requestService
.
request
({
url
:
this
.
url
})
.
then
<
IUpdate
>
(
asJson
)
.
then
(
update
=>
{
if
(
!
update
||
!
update
.
url
||
!
update
.
version
)
{
if
(
!
update
||
!
update
.
url
||
!
update
.
version
||
!
update
.
productVersion
)
{
this
.
emit
(
'
update-not-available
'
);
}
else
{
this
.
emit
(
'
update-available
'
,
null
,
product
.
downloadUrl
,
update
.
v
ersion
);
this
.
emit
(
'
update-available
'
,
null
,
product
.
downloadUrl
,
update
.
productV
ersion
);
}
})
.
then
(
null
,
e
=>
{
...
...
@@ -67,4 +70,8 @@ export class LinuxAutoUpdaterImpl extends EventEmitter {
})
.
then
(()
=>
this
.
currentRequest
=
null
);
}
quitAndInstall
():
void
{
// noop
}
}
src/vs/
cod
e/electron-main/auto-updater.win32.ts
→
src/vs/
platform/updat
e/electron-main/auto-updater.win32.ts
浏览文件 @
1aaf1a80
...
...
@@ -17,9 +17,10 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base';
import
{
download
,
asJson
}
from
'
vs/base/node/request
'
;
import
{
ILifecycleService
}
from
'
vs/code/electron-main/lifecycle
'
;
import
{
IRequestService
}
from
'
vs/platform/request/common/request
'
;
import
{
IAutoUpdater
}
from
'
vs/platform/update/common/update
'
;
import
product
from
'
vs/platform/product
'
;
export
interface
IUpdate
{
interface
IUpdate
{
url
:
string
;
name
:
string
;
releaseNotes
?:
string
;
...
...
@@ -28,19 +29,17 @@ export interface IUpdate {
hash
:
string
;
}
export
class
Win32AutoUpdaterImpl
extends
EventEmitter
{
export
class
Win32AutoUpdaterImpl
extends
EventEmitter
implements
IAutoUpdater
{
private
url
:
string
;
private
currentRequest
:
Promise
;
private
url
:
string
=
null
;
private
currentRequest
:
Promise
=
null
;
private
updatePackagePath
:
string
=
null
;
constructor
(
@
ILifecycleService
private
lifecycleService
:
ILifecycleService
,
@
IRequestService
private
requestService
:
IRequestService
)
{
super
();
this
.
url
=
null
;
this
.
currentRequest
=
null
;
}
get
cachePath
():
TPromise
<
string
>
{
...
...
@@ -91,13 +90,14 @@ export class Win32AutoUpdaterImpl extends EventEmitter {
.
then
(()
=>
updatePackagePath
);
});
}).
then
(
updatePackagePath
=>
{
this
.
updatePackagePath
=
updatePackagePath
;
this
.
emit
(
'
update-downloaded
'
,
{},
update
.
releaseNotes
,
update
.
productVersion
,
new
Date
(),
this
.
url
,
()
=>
this
.
quitAndUpdate
(
updatePackagePath
)
this
.
url
);
});
});
...
...
@@ -117,19 +117,6 @@ export class Win32AutoUpdaterImpl extends EventEmitter {
return
this
.
cachePath
.
then
(
cachePath
=>
path
.
join
(
cachePath
,
`CodeSetup-
${
product
.
quality
}
-
${
version
}
.exe`
));
}
private
quitAndUpdate
(
updatePackagePath
:
string
):
void
{
this
.
lifecycleService
.
quit
().
done
(
vetod
=>
{
if
(
vetod
)
{
return
;
}
spawn
(
updatePackagePath
,
[
'
/silent
'
,
'
/mergetasks=runcode,!desktopicon,!quicklaunchicon
'
],
{
detached
:
true
,
stdio
:
[
'
ignore
'
,
'
ignore
'
,
'
ignore
'
]
});
});
}
private
cleanup
(
exceptVersion
:
string
=
null
):
Promise
{
const
filter
=
exceptVersion
?
one
=>
!
(
new
RegExp
(
`
${
product
.
quality
}
-
${
exceptVersion
}
\\.exe$`
).
test
(
one
))
:
()
=>
true
;
...
...
@@ -141,4 +128,15 @@ export class Win32AutoUpdaterImpl extends EventEmitter {
))
);
}
quitAndInstall
():
void
{
if
(
!
this
.
updatePackagePath
)
{
return
;
}
spawn
(
this
.
updatePackagePath
,
[
'
/silent
'
,
'
/mergetasks=runcode,!desktopicon,!quicklaunchicon
'
],
{
detached
:
true
,
stdio
:
[
'
ignore
'
,
'
ignore
'
,
'
ignore
'
]
});
}
}
src/vs/
code/electron-main/update-manager
.ts
→
src/vs/
platform/update/electron-main/updateService
.ts
浏览文件 @
1aaf1a80
...
...
@@ -8,170 +8,99 @@
import
*
as
fs
from
'
original-fs
'
;
import
*
as
path
from
'
path
'
;
import
*
as
electron
from
'
electron
'
;
import
{
EventEmitter
}
from
'
events
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
Event
,
{
Emitter
,
once
,
filterEvent
}
from
'
vs/base/common/event
'
;
import
{
always
,
Throttler
}
from
'
vs/base/common/async
'
;
import
{
memoize
}
from
'
vs/base/common/decorators
'
;
import
{
fromEventEmitter
}
from
'
vs/base/node/event
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
Win32AutoUpdaterImpl
}
from
'
vs/code/electron-main
/auto-updater.win32
'
;
import
{
LinuxAutoUpdaterImpl
}
from
'
vs/code/electron-main
/auto-updater.linux
'
;
import
{
Win32AutoUpdaterImpl
}
from
'
.
/auto-updater.win32
'
;
import
{
LinuxAutoUpdaterImpl
}
from
'
.
/auto-updater.linux
'
;
import
{
ILifecycleService
}
from
'
vs/code/electron-main/lifecycle
'
;
import
{
createDecorator
,
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IRequestService
}
from
'
vs/platform/request/common/request
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
product
from
'
vs/platform/product
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IUpdateService
,
State
,
IAutoUpdater
,
IUpdate
,
IRawUpdate
}
from
'
vs/platform/update/common/update
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
export
enum
State
{
Uninitialized
,
Idle
,
CheckingForUpdate
,
UpdateAvailable
,
UpdateDownloaded
}
export
enum
ExplicitState
{
Implicit
,
Explicit
}
export
interface
IUpdate
{
releaseNotes
:
string
;
version
:
string
;
date
:
Date
;
quitAndUpdate
:
()
=>
void
;
}
interface
IAutoUpdater
extends
NodeJS
.
EventEmitter
{
setFeedURL
(
url
:
string
):
void
;
checkForUpdates
():
void
;
}
export
const
IUpdateService
=
createDecorator
<
IUpdateService
>
(
'
updateService
'
);
export
interface
IUpdateService
{
_serviceBrand
:
any
;
feedUrl
:
string
;
channel
:
string
;
initialize
():
void
;
state
:
State
;
availableUpdate
:
IUpdate
;
lastCheckDate
:
Date
;
checkForUpdates
(
explicit
:
boolean
):
void
;
on
(
event
:
string
,
listener
:
Function
):
this
;
}
export
class
UpdateManager
extends
EventEmitter
implements
IUpdateService
{
export
class
UpdateService
implements
IUpdateService
{
_serviceBrand
:
any
;
private
_state
:
State
;
private
explicitState
:
ExplicitState
;
private
_availableUpdate
:
IUpdate
;
private
_lastCheckDate
:
Date
;
private
_state
:
State
=
State
.
Uninitialized
;
private
_availableUpdate
:
IUpdate
=
null
;
private
raw
:
IAutoUpdater
;
private
_feedUrl
:
string
;
private
_channel
:
string
;
constructor
(
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
ILifecycleService
private
lifecycleService
:
ILifecycleService
,
@
IConfigurationService
private
configurationService
:
IConfigurationService
,
@
IRequestService
requestService
:
IRequestService
)
{
super
();
this
.
_state
=
State
.
Uninitialized
;
this
.
explicitState
=
ExplicitState
.
Implicit
;
this
.
_availableUpdate
=
null
;
this
.
_lastCheckDate
=
null
;
this
.
_feedUrl
=
null
;
this
.
_channel
=
null
;
if
(
process
.
platform
===
'
win32
'
)
{
this
.
raw
=
instantiationService
.
createInstance
(
Win32AutoUpdaterImpl
);
}
else
if
(
process
.
platform
===
'
linux
'
)
{
this
.
raw
=
instantiationService
.
createInstance
(
LinuxAutoUpdaterImpl
);
}
else
if
(
process
.
platform
===
'
darwin
'
)
{
this
.
raw
=
electron
.
autoUpdater
;
}
if
(
this
.
raw
)
{
this
.
initRaw
();
}
}
private
initRaw
():
void
{
this
.
raw
.
on
(
'
error
'
,
(
event
:
any
,
message
:
string
)
=>
{
this
.
emit
(
'
error
'
,
event
,
message
);
this
.
setState
(
State
.
Idle
);
});
private
throttler
:
Throttler
=
new
Throttler
();
this
.
raw
.
on
(
'
checking-for-update
'
,
()
=>
{
this
.
emit
(
'
checking-for-update
'
);
this
.
setState
(
State
.
CheckingForUpdate
);
});
private
_onError
=
new
Emitter
<
any
>
();
get
onError
():
Event
<
any
>
{
return
this
.
_onError
.
event
;
}
this
.
raw
.
on
(
'
update-available
'
,
(
event
,
url
:
string
,
version
:
string
)
=>
{
this
.
emit
(
'
update-available
'
,
url
,
version
);
private
_onCheckForUpdate
=
new
Emitter
<
void
>
();
get
onCheckForUpdate
():
Event
<
void
>
{
return
this
.
_onCheckForUpdate
.
event
;
}
let
data
:
IUpdate
=
null
;
private
_onUpdateAvailable
=
new
Emitter
<
{
url
:
string
;
version
:
string
;
}
>
();
get
onUpdateAvailable
():
Event
<
{
url
:
string
;
version
:
string
;
}
>
{
return
this
.
_onUpdateAvailable
.
event
;
}
if
(
url
)
{
data
=
{
releaseNotes
:
''
,
version
:
''
,
date
:
new
Date
(),
quitAndUpdate
:
()
=>
electron
.
shell
.
openExternal
(
url
)
};
}
private
_onUpdateNotAvailable
=
new
Emitter
<
boolean
>
();
get
onUpdateNotAvailable
():
Event
<
boolean
>
{
return
this
.
_onUpdateNotAvailable
.
event
;
}
this
.
setState
(
State
.
UpdateAvailable
,
data
);
});
private
_onUpdateReady
=
new
Emitter
<
IUpdate
>
(
);
get
onUpdateReady
():
Event
<
IUpdate
>
{
return
this
.
_onUpdateReady
.
event
;
}
this
.
raw
.
on
(
'
update-not-available
'
,
()
=>
{
this
.
emit
(
'
update-not-available
'
,
this
.
explicitState
===
ExplicitState
.
Explicit
);
this
.
setState
(
State
.
Idle
);
});
private
_onStateChange
=
new
Emitter
<
State
>
();
get
onStateChange
():
Event
<
State
>
{
return
this
.
_onStateChange
.
event
;
}
this
.
raw
.
on
(
'
update-downloaded
'
,
(
event
:
any
,
releaseNotes
:
string
,
version
:
string
,
date
:
Date
,
url
:
string
,
rawQuitAndUpdate
:
()
=>
void
)
=>
{
const
data
:
IUpdate
=
{
releaseNotes
:
releaseNotes
,
version
:
version
,
date
:
date
,
quitAndUpdate
:
()
=>
this
.
quitAndUpdate
(
rawQuitAndUpdate
)
};
@
memoize
private
get
onRawError
():
Event
<
string
>
{
return
fromEventEmitter
(
this
.
raw
,
'
error
'
,
(
_
,
message
)
=>
message
);
}
this
.
emit
(
'
update-downloaded
'
,
data
);
this
.
setState
(
State
.
UpdateDownloaded
,
data
);
}
);
@
memoize
private
get
onRawUpdateNotAvailable
():
Event
<
void
>
{
return
fromEventEmitter
<
void
>
(
this
.
raw
,
'
update-not-available
'
);
}
private
quitAndUpdate
(
rawQuitAndUpdate
:
()
=>
void
):
void
{
this
.
lifecycleService
.
quit
(
true
/* from update */
).
done
(
vetod
=>
{
if
(
vetod
)
{
return
;
}
@
memoize
private
get
onRawUpdateAvailable
():
Event
<
{
url
:
string
;
version
:
string
;
}
>
{
return
filterEvent
(
fromEventEmitter
(
this
.
raw
,
'
update-available
'
,
(
_
,
url
,
version
)
=>
({
url
,
version
})),
({
url
})
=>
!!
url
);
}
// for some reason updating on Mac causes the local storage not to be flushed.
// we workaround this issue by forcing an explicit flush of the storage data.
// see also https://github.com/Microsoft/vscode/issues/172
if
(
process
.
platform
===
'
darwin
'
)
{
electron
.
session
.
defaultSession
.
flushStorageData
();
}
@
memoize
private
get
onRawUpdateDownloaded
():
Event
<
IRawUpdate
>
{
return
fromEventEmitter
(
this
.
raw
,
'
update-downloaded
'
,
(
_
,
releaseNotes
,
version
,
date
,
url
)
=>
({
releaseNotes
,
version
,
date
}));
}
rawQuitAndUpdate
();
})
;
get
state
():
State
{
return
this
.
_state
;
}
public
get
feedUrl
():
string
{
return
this
.
_feedUrl
;
set
state
(
state
:
State
)
{
this
.
_state
=
state
;
this
.
_onStateChange
.
fire
(
state
);
}
public
get
channel
():
string
{
return
this
.
_
channel
;
get
availableUpdate
():
IUpdate
{
return
this
.
_
availableUpdate
;
}
public
initialize
():
void
{
if
(
this
.
feedUrl
)
{
return
;
// already initialized
constructor
(
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
ILifecycleService
private
lifecycleService
:
ILifecycleService
,
@
IConfigurationService
private
configurationService
:
IConfigurationService
,
@
ITelemetryService
private
telemetryService
:
ITelemetryService
)
{
if
(
process
.
platform
===
'
win32
'
)
{
this
.
raw
=
instantiationService
.
createInstance
(
Win32AutoUpdaterImpl
);
}
else
if
(
process
.
platform
===
'
linux
'
)
{
this
.
raw
=
instantiationService
.
createInstance
(
LinuxAutoUpdaterImpl
);
}
else
if
(
process
.
platform
===
'
darwin
'
)
{
this
.
raw
=
electron
.
autoUpdater
;
}
else
{
return
;
}
telemetryService
.
publicLog
(
'
whattt
'
,
{
yeah
:
123
});
const
channel
=
this
.
getUpdateChannel
();
const
feedUrl
=
this
.
getUpdateFeedUrl
(
channel
);
...
...
@@ -185,48 +114,82 @@ export class UpdateManager extends EventEmitter implements IUpdateService {
return
;
// application not signed
}
this
.
_channel
=
channel
;
this
.
_feedUrl
=
feedUrl
;
this
.
state
=
State
.
Idle
;
this
.
setState
(
State
.
Idle
);
// Start checking for updates after 30 seconds
this
.
scheduleCheckForUpdates
(
30
*
1000
)
.
done
(
null
,
err
=>
console
.
error
(
err
));
}
// Check for updates on startup after 30 seconds
let
timer
=
setTimeout
(()
=>
this
.
checkForUpdates
(),
30
*
1000
);
private
scheduleCheckForUpdates
(
delay
=
60
*
60
*
1000
):
TPromise
<
void
>
{
return
TPromise
.
timeout
(
delay
)
.
then
(()
=>
this
.
checkForUpdates
())
.
then
(
update
=>
{
if
(
update
)
{
// Update found, no need to check more
return
TPromise
.
as
(
null
);
}
// Check again after 1 hour
return
this
.
scheduleCheckForUpdates
(
60
*
60
*
1000
);
});
}
// Clear timer when checking for update
this
.
on
(
'
error
'
,
(
error
:
any
,
message
:
string
)
=>
console
.
error
(
error
,
message
));
checkForUpdates
(
explicit
=
false
):
TPromise
<
IUpdate
>
{
return
this
.
throttler
.
queue
(()
=>
this
.
_checkForUpdates
(
explicit
));
}
// Clear timer when checking for update
this
.
on
(
'
checking-for-update
'
,
()
=>
clearTimeout
(
timer
));
private
_checkForUpdates
(
explicit
:
boolean
):
TPromise
<
IUpdate
>
{
if
(
this
.
state
!==
State
.
Idle
)
{
return
TPromise
.
as
(
null
);
}
// If update not found, try again in 1 hour
this
.
on
(
'
update-not-available
'
,
()
=>
{
timer
=
setTimeout
(()
=>
this
.
checkForUpdates
(),
60
*
60
*
1000
);
});
}
this
.
_onCheckForUpdate
.
fire
();
this
.
state
=
State
.
CheckingForUpdate
;
const
listeners
:
IDisposable
[]
=
[];
const
result
=
new
TPromise
<
IUpdate
>
((
c
,
e
)
=>
{
once
(
this
.
onRawError
)(
e
,
null
,
listeners
);
once
(
this
.
onRawUpdateNotAvailable
)(()
=>
c
(
null
),
null
,
listeners
);
once
(
this
.
onRawUpdateAvailable
)(({
url
,
version
})
=>
url
&&
c
({
url
,
version
}),
null
,
listeners
);
once
(
this
.
onRawUpdateDownloaded
)(({
version
,
date
,
releaseNotes
})
=>
c
({
version
,
date
,
releaseNotes
}),
null
,
listeners
);
this
.
raw
.
checkForUpdates
();
}).
then
(
update
=>
{
if
(
!
update
)
{
this
.
_onUpdateNotAvailable
.
fire
(
explicit
);
this
.
state
=
State
.
Idle
;
this
.
telemetryService
.
publicLog
(
'
update:notAvailable
'
,
{
explicit
});
}
else
if
(
update
.
url
)
{
const
data
:
IUpdate
=
{
url
:
update
.
url
,
releaseNotes
:
''
,
version
:
update
.
version
,
date
:
new
Date
()
};
public
get
state
():
State
{
return
this
.
_state
;
}
this
.
_availableUpdate
=
data
;
this
.
_onUpdateAvailable
.
fire
({
url
:
update
.
url
,
version
:
update
.
version
})
;
this
.
state
=
State
.
UpdateAvailable
;
public
get
availableUpdate
():
IUpdate
{
return
this
.
_availableUpdate
;
}
}
else
{
const
data
:
IUpdate
=
{
releaseNotes
:
update
.
releaseNotes
,
version
:
update
.
version
,
date
:
update
.
date
};
public
get
lastCheckDate
():
Date
{
return
this
.
_lastCheckDate
;
}
this
.
_availableUpdate
=
data
;
this
.
_onUpdateReady
.
fire
(
data
);
this
.
state
=
State
.
UpdateDownloaded
;
this
.
telemetryService
.
publicLog
(
'
update:downloaded
'
,
{
version
:
update
.
version
});
}
public
checkForUpdates
(
explicit
=
false
):
void
{
this
.
explicitState
=
explicit
?
ExplicitState
.
Explicit
:
ExplicitState
.
Implicit
;
this
.
_lastCheckDate
=
new
Date
();
this
.
raw
.
checkForUpdates
();
}
return
update
;
});
private
setState
(
state
:
State
,
availableUpdate
:
IUpdate
=
null
):
void
{
this
.
_state
=
state
;
this
.
_availableUpdate
=
availableUpdate
;
this
.
emit
(
'
change
'
);
return
always
(
result
,
()
=>
dispose
(
listeners
));
}
private
getUpdateChannel
():
string
{
...
...
@@ -253,4 +216,32 @@ export class UpdateManager extends EventEmitter implements IUpdateService {
return
`
${
product
.
updateUrl
}
/api/update/
${
platform
}
/
${
channel
}
/
${
product
.
commit
}
`
;
}
}
quitAndInstall
():
TPromise
<
void
>
{
if
(
!
this
.
_availableUpdate
)
{
return
TPromise
.
as
(
null
);
}
if
(
this
.
_availableUpdate
.
url
)
{
electron
.
shell
.
openExternal
(
this
.
_availableUpdate
.
url
);
return
TPromise
.
as
(
null
);
}
this
.
lifecycleService
.
quit
(
true
/* from update */
).
done
(
vetod
=>
{
if
(
vetod
)
{
return
;
}
// for some reason updating on Mac causes the local storage not to be flushed.
// we workaround this issue by forcing an explicit flush of the storage data.
// see also https://github.com/Microsoft/vscode/issues/172
if
(
process
.
platform
===
'
darwin
'
)
{
electron
.
session
.
defaultSession
.
flushStorageData
();
}
this
.
raw
.
quitAndInstall
();
});
return
TPromise
.
as
(
null
);
}
}
\ No newline at end of file
src/vs/workbench/electron-browser/shell.ts
浏览文件 @
1aaf1a80
...
...
@@ -81,6 +81,8 @@ import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/
import
{
IExtensionManagementChannel
,
ExtensionManagementChannelClient
}
from
'
vs/platform/extensionManagement/common/extensionManagementIpc
'
;
import
{
IExtensionManagementService
,
IExtensionEnablementService
}
from
'
vs/platform/extensionManagement/common/extensionManagement
'
;
import
{
ExtensionEnablementService
}
from
'
vs/platform/extensionManagement/common/extensionEnablementService
'
;
import
{
UpdateChannelClient
}
from
'
vs/platform/update/common/updateIpc
'
;
import
{
IUpdateService
}
from
'
vs/platform/update/common/update
'
;
import
{
URLChannelClient
}
from
'
vs/platform/url/common/urlIpc
'
;
import
{
IURLService
}
from
'
vs/platform/url/common/url
'
;
import
{
ReloadWindowAction
}
from
'
vs/workbench/electron-browser/actions
'
;
...
...
@@ -350,6 +352,10 @@ export class WorkbenchShell {
const
integrityService
=
instantiationService
.
createInstance
(
IntegrityServiceImpl
);
serviceCollection
.
set
(
IIntegrityService
,
integrityService
);
const
updateChannel
=
mainProcessClient
.
getChannel
(
'
update
'
);
const
updateChannelClient
=
new
UpdateChannelClient
(
updateChannel
);
serviceCollection
.
set
(
IUpdateService
,
updateChannelClient
);
const
urlChannel
=
mainProcessClient
.
getChannel
(
'
url
'
);
const
urlChannelClient
=
new
URLChannelClient
(
urlChannel
,
windowIPCService
.
getWindowId
());
serviceCollection
.
set
(
IURLService
,
urlChannelClient
);
...
...
src/vs/workbench/parts/update/electron-browser/update.ts
浏览文件 @
1aaf1a80
...
...
@@ -9,7 +9,6 @@ import nls = require('vs/nls');
import
severity
from
'
vs/base/common/severity
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
Action
}
from
'
vs/base/common/actions
'
;
import
{
ipcRenderer
as
ipc
}
from
'
electron
'
;
import
{
IMessageService
,
CloseAction
,
Severity
}
from
'
vs/platform/message/common/message
'
;
import
pkg
from
'
vs/platform/package
'
;
import
product
from
'
vs/platform/product
'
;
...
...
@@ -25,21 +24,18 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import
{
IOpenerService
}
from
'
vs/platform/opener/common/opener
'
;
import
{
IWorkbenchContribution
}
from
'
vs/workbench/common/contributions
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
IUpdateService
}
from
'
vs/platform/update/common/update
'
;
import
*
as
semver
from
'
semver
'
;
interface
IUpdate
{
releaseNotes
:
string
;
version
:
string
;
date
:
string
;
}
class
ApplyUpdateAction
extends
Action
{
constructor
(
@
IUpdateService
private
updateService
:
IUpdateService
)
{
super
(
'
update.applyUpdate
'
,
nls
.
localize
(
'
updateNow
'
,
"
Update Now
"
),
null
,
true
);
}
const
ApplyUpdateAction
=
new
Action
(
'
update.applyUpdate
'
,
nls
.
localize
(
'
updateNow
'
,
"
Update Now
"
),
null
,
true
,
()
=>
{
ipc
.
send
(
'
vscode:update-apply
'
);
return
TPromise
.
as
(
true
);
}
);
run
():
TPromise
<
void
>
{
return
this
.
updateService
.
quitAndInstall
();
}
}
const
NotNowAction
=
new
Action
(
'
update.later
'
,
...
...
@@ -173,13 +169,16 @@ export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesActio
}
}
export
const
DownloadAction
=
(
url
:
string
)
=>
new
Action
(
'
update.download
'
,
nls
.
localize
(
'
downloadNow
'
,
"
Download Now
"
),
null
,
true
,
()
=>
{
window
.
open
(
url
);
return
TPromise
.
as
(
true
);
}
);
export
class
DownloadAction
extends
Action
{
constructor
(
private
url
:
string
,
@
IUpdateService
private
updateService
:
IUpdateService
)
{
super
(
'
update.download
'
,
nls
.
localize
(
'
downloadNow
'
,
"
Download Now
"
),
null
,
true
);
}
run
():
TPromise
<
void
>
{
return
this
.
updateService
.
quitAndInstall
();
}
}
const
LinkAction
=
(
id
:
string
,
message
:
string
,
licenseUrl
:
string
)
=>
new
Action
(
id
,
message
,
null
,
true
,
...
...
@@ -196,6 +195,7 @@ export class UpdateContribution implements IWorkbenchContribution {
@
IStorageService
storageService
:
IStorageService
,
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
IMessageService
messageService
:
IMessageService
,
@
IUpdateService
updateService
:
IUpdateService
,
@
IWorkbenchEditorService
editorService
:
IWorkbenchEditorService
)
{
const
lastVersion
=
storageService
.
get
(
UpdateContribution
.
KEY
,
StorageScope
.
GLOBAL
,
''
);
...
...
@@ -250,26 +250,31 @@ export class UpdateContribution implements IWorkbenchContribution {
storageService
.
store
(
UpdateContribution
.
KEY
,
pkg
.
version
,
StorageScope
.
GLOBAL
);
ipc
.
on
(
'
vscode:update-downloaded
'
,
(
event
,
data
:
string
)
=>
{
const
update
=
JSON
.
parse
(
data
)
as
IUpdate
;
updateService
.
onUpdateReady
(
update
=>
{
const
applyUpdateAction
=
instantiationService
.
createInstance
(
ApplyUpdateAction
)
;
const
releaseNotesAction
=
instantiationService
.
createInstance
(
ShowReleaseNotesAction
,
false
,
update
.
version
);
messageService
.
show
(
severity
.
Info
,
{
message
:
nls
.
localize
(
'
updateAvailable
'
,
"
{0} will be updated after it restarts.
"
,
product
.
nameLong
),
actions
:
[
A
pplyUpdateAction
,
NotNowAction
,
releaseNotesAction
]
actions
:
[
a
pplyUpdateAction
,
NotNowAction
,
releaseNotesAction
]
});
});
ipc
.
on
(
'
vscode:update-available
'
,
(
event
,
url
:
string
,
version
:
string
)
=>
{
const
releaseNotesAction
=
instantiationService
.
createInstance
(
ShowReleaseNotesAction
,
false
,
version
);
updateService
.
onUpdateAvailable
(
update
=>
{
const
downloadAction
=
instantiationService
.
createInstance
(
DownloadAction
,
update
.
version
);
const
releaseNotesAction
=
instantiationService
.
createInstance
(
ShowReleaseNotesAction
,
false
,
update
.
version
);
messageService
.
show
(
severity
.
Info
,
{
message
:
nls
.
localize
(
'
thereIsUpdateAvailable
'
,
"
There is an available update.
"
),
actions
:
[
DownloadAction
(
url
)
,
NotNowAction
,
releaseNotesAction
]
actions
:
[
downloadAction
,
NotNowAction
,
releaseNotesAction
]
});
});
ipc
.
on
(
'
vscode:update-not-available
'
,
()
=>
{
updateService
.
onUpdateNotAvailable
(
explicit
=>
{
if
(
!
explicit
)
{
return
;
}
messageService
.
show
(
severity
.
Info
,
nls
.
localize
(
'
noUpdatesAvailable
'
,
"
There are no updates currently available.
"
));
});
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录