Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gzupanda
code-server
提交
8122b7f6
C
code-server
项目概览
gzupanda
/
code-server
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
code-server
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
8122b7f6
编写于
1月 17, 2020
作者:
A
Asher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Remove unused upload service
No longer needed since VS Code has their own now.
上级
25f18bed
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
0 addition
and
374 deletion
+0
-374
src/browser/client.ts
src/browser/client.ts
+0
-2
src/browser/upload.ts
src/browser/upload.ts
+0
-372
未找到文件。
src/browser/client.ts
浏览文件 @
8122b7f6
...
...
@@ -10,7 +10,6 @@ import { Registry } from "vs/platform/registry/common/platform";
import
{
PersistentConnectionEventType
}
from
"
vs/platform/remote/common/remoteAgentConnection
"
;
import
{
ITelemetryService
}
from
"
vs/platform/telemetry/common/telemetry
"
;
import
{
coderApi
,
vscodeApi
}
from
"
vs/server/src/browser/api
"
;
import
{
IUploadService
,
UploadService
}
from
"
vs/server/src/browser/upload
"
;
import
{
INodeProxyService
,
NodeProxyChannelClient
}
from
"
vs/server/src/common/nodeProxy
"
;
import
{
TelemetryChannelClient
}
from
"
vs/server/src/common/telemetry
"
;
import
{
split
}
from
"
vs/server/src/common/util
"
;
...
...
@@ -71,7 +70,6 @@ class NodeProxyService extends NodeProxyChannelClient implements INodeProxyServi
registerSingleton
(
ILocalizationsService
,
LocalizationsService
);
registerSingleton
(
INodeProxyService
,
NodeProxyService
);
registerSingleton
(
ITelemetryService
,
TelemetryService
);
registerSingleton
(
IUploadService
,
UploadService
,
true
);
/**
* This is called by vs/workbench/browser/web.main.ts after the workbench has
...
...
src/browser/upload.ts
已删除
100644 → 0
浏览文件 @
25f18bed
import
{
DesktopDragAndDropData
}
from
"
vs/base/browser/ui/list/listView
"
;
import
{
VSBuffer
,
VSBufferReadableStream
}
from
"
vs/base/common/buffer
"
;
import
{
Disposable
}
from
"
vs/base/common/lifecycle
"
;
import
*
as
path
from
"
vs/base/common/path
"
;
import
{
URI
}
from
"
vs/base/common/uri
"
;
import
{
generateUuid
}
from
"
vs/base/common/uuid
"
;
import
{
IFileService
}
from
"
vs/platform/files/common/files
"
;
import
{
createDecorator
,
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
INotificationService
,
Severity
}
from
"
vs/platform/notification/common/notification
"
;
import
{
IProgress
,
IProgressService
,
IProgressStep
,
ProgressLocation
}
from
"
vs/platform/progress/common/progress
"
;
import
{
IWorkspaceContextService
}
from
"
vs/platform/workspace/common/workspace
"
;
import
{
IWorkspacesService
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
ExplorerItem
}
from
"
vs/workbench/contrib/files/common/explorerModel
"
;
import
{
IEditorGroup
}
from
"
vs/workbench/services/editor/common/editorGroupsService
"
;
import
{
IEditorService
}
from
"
vs/workbench/services/editor/common/editorService
"
;
export
const
IUploadService
=
createDecorator
<
IUploadService
>
(
"
uploadService
"
);
export
interface
IUploadService
{
_serviceBrand
:
undefined
;
handleDrop
(
event
:
DragEvent
,
resolveTargetGroup
:
()
=>
IEditorGroup
|
undefined
,
afterDrop
:
(
targetGroup
:
IEditorGroup
|
undefined
)
=>
void
,
targetIndex
?:
number
):
Promise
<
void
>
;
handleExternalDrop
(
data
:
DesktopDragAndDropData
,
target
:
ExplorerItem
,
originalEvent
:
DragEvent
):
Promise
<
void
>
;
}
export
class
UploadService
extends
Disposable
implements
IUploadService
{
public
_serviceBrand
:
undefined
;
public
upload
:
Upload
;
public
constructor
(
@
IInstantiationService
instantiationService
:
IInstantiationService
,
@
IWorkspaceContextService
private
readonly
contextService
:
IWorkspaceContextService
,
@
IWorkspacesService
private
readonly
workspacesService
:
IWorkspacesService
,
@
IEditorService
private
readonly
editorService
:
IEditorService
,
)
{
super
();
this
.
upload
=
instantiationService
.
createInstance
(
Upload
);
}
public
async
handleDrop
(
event
:
DragEvent
,
resolveTargetGroup
:
()
=>
IEditorGroup
|
undefined
,
afterDrop
:
(
targetGroup
:
IEditorGroup
|
undefined
)
=>
void
,
targetIndex
?:
number
):
Promise
<
void
>
{
// TODO: should use the workspace for the editor it was dropped on?
const
target
=
this
.
contextService
.
getWorkspace
().
folders
[
0
].
uri
;
const
uris
=
(
await
this
.
upload
.
uploadDropped
(
event
,
target
)).
map
((
u
)
=>
URI
.
file
(
u
));
if
(
uris
.
length
>
0
)
{
await
this
.
workspacesService
.
addRecentlyOpened
(
uris
.
map
((
u
)
=>
({
fileUri
:
u
})));
}
const
editors
=
uris
.
map
((
uri
)
=>
({
resource
:
uri
,
options
:
{
pinned
:
true
,
index
:
targetIndex
,
},
}));
const
targetGroup
=
resolveTargetGroup
();
this
.
editorService
.
openEditors
(
editors
,
targetGroup
);
afterDrop
(
targetGroup
);
}
public
async
handleExternalDrop
(
_data
:
DesktopDragAndDropData
,
target
:
ExplorerItem
,
originalEvent
:
DragEvent
):
Promise
<
void
>
{
await
this
.
upload
.
uploadDropped
(
originalEvent
,
target
.
resource
);
}
}
/**
* There doesn't seem to be a provided type for entries, so here is an
* incomplete version.
*/
interface
IEntry
{
name
:
string
;
isFile
:
boolean
;
file
:
(
cb
:
(
file
:
File
)
=>
void
)
=>
void
;
createReader
:
()
=>
({
readEntries
:
(
cb
:
(
entries
:
Array
<
IEntry
>
)
=>
void
)
=>
void
;
});
}
/**
* Handles file uploads.
*/
class
Upload
{
private
readonly
maxParallelUploads
=
100
;
private
readonly
uploadingFiles
=
new
Map
<
string
,
Reader
|
undefined
>
();
private
readonly
fileQueue
=
new
Map
<
string
,
File
>
();
private
progress
:
IProgress
<
IProgressStep
>
|
undefined
;
private
uploadPromise
:
Promise
<
string
[]
>
|
undefined
;
private
resolveUploadPromise
:
(()
=>
void
)
|
undefined
;
private
uploadedFilePaths
=
<
string
[]
>
[];
private
_total
=
0
;
private
_uploaded
=
0
;
private
lastPercent
=
0
;
public
constructor
(
@
INotificationService
private
notificationService
:
INotificationService
,
@
IProgressService
private
progressService
:
IProgressService
,
@
IFileService
private
fileService
:
IFileService
,
)
{}
/**
* Upload dropped files. This will try to upload everything it can. Errors
* will show via notifications. If an upload operation is ongoing, the files
* will be added to that operation.
*/
public
async
uploadDropped
(
event
:
DragEvent
,
uploadDir
:
URI
):
Promise
<
string
[]
>
{
await
this
.
queueFiles
(
event
,
uploadDir
);
if
(
!
this
.
uploadPromise
)
{
this
.
uploadPromise
=
this
.
progressService
.
withProgress
({
cancellable
:
true
,
location
:
ProgressLocation
.
Notification
,
title
:
"
Uploading files...
"
,
},
(
progress
)
=>
{
return
new
Promise
((
resolve
):
void
=>
{
this
.
progress
=
progress
;
this
.
resolveUploadPromise
=
():
void
=>
{
const
uploaded
=
this
.
uploadedFilePaths
;
this
.
uploadPromise
=
undefined
;
this
.
resolveUploadPromise
=
undefined
;
this
.
uploadedFilePaths
=
[];
this
.
lastPercent
=
0
;
this
.
_uploaded
=
0
;
this
.
_total
=
0
;
resolve
(
uploaded
);
};
});
},
()
=>
this
.
cancel
());
}
this
.
uploadFiles
();
return
this
.
uploadPromise
;
}
/**
* Cancel all file uploads.
*/
public
async
cancel
():
Promise
<
void
>
{
this
.
fileQueue
.
clear
();
this
.
uploadingFiles
.
forEach
((
r
)
=>
r
&&
r
.
abort
());
}
private
get
total
():
number
{
return
this
.
_total
;
}
private
set
total
(
total
:
number
)
{
this
.
_total
=
total
;
this
.
updateProgress
();
}
private
get
uploaded
():
number
{
return
this
.
_uploaded
;
}
private
set
uploaded
(
uploaded
:
number
)
{
this
.
_uploaded
=
uploaded
;
this
.
updateProgress
();
}
private
updateProgress
():
void
{
if
(
this
.
progress
&&
this
.
total
>
0
)
{
const
percent
=
Math
.
floor
((
this
.
uploaded
/
this
.
total
)
*
100
);
this
.
progress
.
report
({
increment
:
percent
-
this
.
lastPercent
});
this
.
lastPercent
=
percent
;
}
}
/**
* Upload as many files as possible. When finished, resolve the upload
* promise.
*/
private
uploadFiles
():
void
{
while
(
this
.
fileQueue
.
size
>
0
&&
this
.
uploadingFiles
.
size
<
this
.
maxParallelUploads
)
{
const
[
path
,
file
]
=
this
.
fileQueue
.
entries
().
next
().
value
;
this
.
fileQueue
.
delete
(
path
);
if
(
this
.
uploadingFiles
.
has
(
path
))
{
this
.
notificationService
.
error
(
new
Error
(
`Already uploading
${
path
}
`
));
}
else
{
this
.
uploadingFiles
.
set
(
path
,
undefined
);
this
.
uploadFile
(
path
,
file
).
catch
((
error
)
=>
{
this
.
notificationService
.
error
(
error
);
}).
finally
(()
=>
{
this
.
uploadingFiles
.
delete
(
path
);
this
.
uploadFiles
();
});
}
}
if
(
this
.
fileQueue
.
size
===
0
&&
this
.
uploadingFiles
.
size
===
0
)
{
this
.
resolveUploadPromise
!
();
}
}
/**
* Upload a file, asking to override if necessary.
*/
private
async
uploadFile
(
filePath
:
string
,
file
:
File
):
Promise
<
void
>
{
const
uri
=
URI
.
file
(
filePath
);
if
(
await
this
.
fileService
.
exists
(
uri
))
{
const
overwrite
=
await
new
Promise
<
boolean
>
((
resolve
):
void
=>
{
this
.
notificationService
.
prompt
(
Severity
.
Error
,
`
${
filePath
}
already exists. Overwrite?`
,
[
{
label
:
"
Yes
"
,
run
:
():
void
=>
resolve
(
true
)
},
{
label
:
"
No
"
,
run
:
():
void
=>
resolve
(
false
)
},
],
{
onCancel
:
()
=>
resolve
(
false
)
},
);
});
if
(
!
overwrite
)
{
return
;
}
}
const
tempUri
=
uri
.
with
({
path
:
path
.
join
(
path
.
dirname
(
uri
.
path
),
`.code-server-partial-upload-
${
path
.
basename
(
uri
.
path
)}
-
${
generateUuid
()}
`
,
),
});
const
reader
=
new
Reader
(
file
);
reader
.
on
(
"
data
"
,
(
data
)
=>
{
if
(
data
&&
data
.
byteLength
>
0
)
{
this
.
uploaded
+=
data
.
byteLength
;
}
});
this
.
uploadingFiles
.
set
(
filePath
,
reader
);
await
this
.
fileService
.
writeFile
(
tempUri
,
reader
);
if
(
reader
.
aborted
)
{
this
.
uploaded
+=
(
file
.
size
-
reader
.
offset
);
await
this
.
fileService
.
del
(
tempUri
);
}
else
{
await
this
.
fileService
.
move
(
tempUri
,
uri
,
true
);
this
.
uploadedFilePaths
.
push
(
filePath
);
}
}
/**
* Queue files from a drop event. We have to get the files first; we can't do
* it in tandem with uploading or the entries will disappear.
*/
private
async
queueFiles
(
event
:
DragEvent
,
uploadDir
:
URI
):
Promise
<
void
>
{
const
promises
:
Array
<
Promise
<
void
>>
=
[];
for
(
let
i
=
0
;
event
.
dataTransfer
&&
event
.
dataTransfer
.
items
&&
i
<
event
.
dataTransfer
.
items
.
length
;
++
i
)
{
const
item
=
event
.
dataTransfer
.
items
[
i
];
if
(
typeof
item
.
webkitGetAsEntry
===
"
function
"
)
{
promises
.
push
(
this
.
traverseItem
(
item
.
webkitGetAsEntry
(),
uploadDir
.
fsPath
));
}
else
{
const
file
=
item
.
getAsFile
();
if
(
file
)
{
this
.
addFile
(
uploadDir
.
fsPath
+
"
/
"
+
file
.
name
,
file
);
}
}
}
await
Promise
.
all
(
promises
);
}
/**
* Traverses an entry and add files to the queue.
*/
private
async
traverseItem
(
entry
:
IEntry
,
path
:
string
):
Promise
<
void
>
{
if
(
entry
.
isFile
)
{
return
new
Promise
<
void
>
((
resolve
):
void
=>
{
entry
.
file
((
file
)
=>
{
resolve
(
this
.
addFile
(
path
+
"
/
"
+
file
.
name
,
file
));
});
});
}
path
+=
"
/
"
+
entry
.
name
;
await
new
Promise
((
resolve
):
void
=>
{
const
promises
:
Array
<
Promise
<
void
>>
=
[];
const
dirReader
=
entry
.
createReader
();
// According to the spec, readEntries() must be called until it calls
// the callback with an empty array.
const
readEntries
=
():
void
=>
{
dirReader
.
readEntries
((
entries
)
=>
{
if
(
entries
.
length
===
0
)
{
Promise
.
all
(
promises
).
then
(
resolve
).
catch
((
error
)
=>
{
this
.
notificationService
.
error
(
error
);
resolve
();
});
}
else
{
promises
.
push
(...
entries
.
map
((
c
)
=>
this
.
traverseItem
(
c
,
path
)));
readEntries
();
}
});
};
readEntries
();
});
}
/**
* Add a file to the queue.
*/
private
addFile
(
path
:
string
,
file
:
File
):
void
{
this
.
total
+=
file
.
size
;
this
.
fileQueue
.
set
(
path
,
file
);
}
}
class
Reader
implements
VSBufferReadableStream
{
private
_offset
=
0
;
private
readonly
size
=
32000
;
// ~32kb max while reading in the file.
private
_aborted
=
false
;
private
readonly
reader
=
new
FileReader
();
private
paused
=
true
;
private
buffer
?:
VSBuffer
;
private
callbacks
=
new
Map
<
string
,
Array
<
(...
args
:
any
[])
=>
void
>>
();
public
constructor
(
private
readonly
file
:
File
)
{
this
.
reader
.
addEventListener
(
"
load
"
,
this
.
onLoad
);
}
public
get
offset
():
number
{
return
this
.
_offset
;
}
public
get
aborted
():
boolean
{
return
this
.
_aborted
;
}
public
on
(
event
:
"
data
"
|
"
error
"
|
"
end
"
,
callback
:
(...
args
:
any
[])
=>
void
):
void
{
if
(
!
this
.
callbacks
.
has
(
event
))
{
this
.
callbacks
.
set
(
event
,
[]);
}
this
.
callbacks
.
get
(
event
)
!
.
push
(
callback
);
if
(
this
.
aborted
)
{
return
this
.
emit
(
"
error
"
,
new
Error
(
"
stream has been aborted
"
));
}
else
if
(
this
.
done
)
{
return
this
.
emit
(
"
error
"
,
new
Error
(
"
stream has ended
"
));
}
else
if
(
event
===
"
end
"
)
{
// Once this is being listened to we can safely start outputting data.
this
.
resume
();
}
}
public
abort
=
():
void
=>
{
this
.
_aborted
=
true
;
this
.
reader
.
abort
();
this
.
reader
.
removeEventListener
(
"
load
"
,
this
.
onLoad
);
this
.
emit
(
"
end
"
);
}
public
pause
():
void
{
this
.
paused
=
true
;
}
public
resume
():
void
{
if
(
this
.
paused
)
{
this
.
paused
=
false
;
this
.
readNextChunk
();
}
}
public
destroy
():
void
{
this
.
abort
();
}
private
onLoad
=
():
void
=>
{
this
.
buffer
=
VSBuffer
.
wrap
(
new
Uint8Array
(
this
.
reader
.
result
as
ArrayBuffer
));
if
(
!
this
.
paused
)
{
this
.
readNextChunk
();
}
}
private
readNextChunk
():
void
{
if
(
this
.
buffer
)
{
this
.
_offset
+=
this
.
buffer
.
byteLength
;
this
.
emit
(
"
data
"
,
this
.
buffer
);
this
.
buffer
=
undefined
;
}
if
(
!
this
.
paused
)
{
// Could be paused during the data event.
if
(
this
.
done
)
{
this
.
emit
(
"
end
"
);
}
else
{
this
.
reader
.
readAsArrayBuffer
(
this
.
file
.
slice
(
this
.
offset
,
this
.
offset
+
this
.
size
));
}
}
}
private
emit
(
event
:
"
data
"
|
"
error
"
|
"
end
"
,
...
args
:
any
[]):
void
{
if
(
this
.
callbacks
.
has
(
event
))
{
this
.
callbacks
.
get
(
event
)
!
.
forEach
((
cb
)
=>
cb
(...
args
));
}
}
private
get
done
():
boolean
{
return
this
.
offset
>=
this
.
file
.
size
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录