Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
d1b9a70d
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,发现更多精彩内容 >>
提交
d1b9a70d
编写于
11月 09, 2017
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
git: data uris
上级
1a54aa89
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
229 addition
and
39 deletion
+229
-39
extensions/git/npm-shrinkwrap.json
extensions/git/npm-shrinkwrap.json
+40
-12
extensions/git/package.json
extensions/git/package.json
+3
-1
extensions/git/src/commands.ts
extensions/git/src/commands.ts
+47
-24
extensions/git/src/git.ts
extensions/git/src/git.ts
+55
-1
extensions/git/src/repository.ts
extensions/git/src/repository.ts
+16
-1
extensions/git/src/util.ts
extensions/git/src/util.ts
+68
-0
未找到文件。
extensions/git/npm-shrinkwrap.json
浏览文件 @
d1b9a70d
{
"name"
:
"git"
,
"version"
:
"0.0.1"
,
"lockfileVersion"
:
1
,
"requires"
:
true
,
"dependencies"
:
{
"@types/file-type"
:
{
"version"
:
"5.2.1"
,
"resolved"
:
"https://registry.npmjs.org/@types/file-type/-/file-type-5.2.1.tgz"
,
"integrity"
:
"sha512-Im0cJaIPJbbpuW91OrjXnqWPZCJK/tcFy2cFX+1qjG1gubgVZPPO9OVsTVAjotN4I1E6FAV0eIqt+rR8Y1c3iA=="
,
"dev"
:
true
,
"requires"
:
{
"@types/node"
:
"8.0.50"
},
"dependencies"
:
{
"@types/node"
:
{
"version"
:
"8.0.50"
,
"resolved"
:
"https://registry.npmjs.org/@types/node/-/node-8.0.50.tgz"
,
"integrity"
:
"sha512-N9OVsMBspboNvYaLAQnLEhb2eQ96lavogMR5LoH5k8nb1PvBZHSBFhzhsq2LNzGTBBOtBviOc1GiSu+wlM/pGw=="
,
"dev"
:
true
}
}
},
"applicationinsights"
:
{
"version"
:
"0.18.0"
,
"
from"
:
"applicationinsights@0.18.0
"
,
"
resolved"
:
"https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz
"
"
resolved"
:
"https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz
"
,
"
integrity"
:
"sha1-Fi67SKODQIvE3kTbMrQXMH9Fu8E=
"
},
"byline"
:
{
"version"
:
"5.0.0"
,
"from"
:
"byline@latest"
,
"resolved"
:
"https://registry.npmjs.org/byline/-/byline-5.0.0.tgz"
"resolved"
:
"https://registry.npmjs.org/byline/-/byline-5.0.0.tgz"
,
"integrity"
:
"sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE="
},
"file-type"
:
{
"version"
:
"7.2.0"
,
"resolved"
:
"https://registry.npmjs.org/file-type/-/file-type-7.2.0.tgz"
,
"integrity"
:
"sha1-ETz+1S4daVmrgCSJBuLyWozcy3Q="
},
"iconv-lite"
:
{
"version"
:
"0.4.19"
,
"
from"
:
"iconv-lite@0.4.19
"
,
"
resolved"
:
"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz
"
"
resolved"
:
"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz
"
,
"
integrity"
:
"sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=
"
},
"vscode-extension-telemetry"
:
{
"version"
:
"0.0.8"
,
"from"
:
"vscode-extension-telemetry@>=0.0.8 <0.0.9"
,
"resolved"
:
"https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
"resolved"
:
"https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
,
"integrity"
:
"sha1-ImG/+Ya2aQpvH3RqRaxb0fhdKeA="
,
"requires"
:
{
"applicationinsights"
:
"0.18.0"
,
"winreg"
:
"1.2.3"
}
},
"vscode-nls"
:
{
"version"
:
"2.0.2"
,
"
from"
:
"vscode-nls@>=2.0.1 <3.0.0
"
,
"
resolved"
:
"https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz
"
"
resolved"
:
"https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz
"
,
"
integrity"
:
"sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto=
"
},
"winreg"
:
{
"version"
:
"1.2.3"
,
"
from"
:
"winreg@1.2.3
"
,
"
resolved"
:
"https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz
"
"
resolved"
:
"https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz
"
,
"
integrity"
:
"sha1-k60RayaW2ofVj3JlqPzqUlSpZdU=
"
}
}
}
extensions/git/package.json
浏览文件 @
d1b9a70d
...
...
@@ -909,14 +909,16 @@
},
"dependencies"
:
{
"byline"
:
"^5.0.0"
,
"file-type"
:
"^7.2.0"
,
"iconv-lite"
:
"0.4.19"
,
"vscode-extension-telemetry"
:
"0.0.8"
,
"vscode-nls"
:
"2.0.2"
},
"devDependencies"
:
{
"@types/byline"
:
"4.2.31"
,
"@types/file-type"
:
"^5.2.1"
,
"@types/mocha"
:
"2.2.43"
,
"@types/node"
:
"7.0.43"
,
"@types/byline"
:
"4.2.31"
,
"mocha"
:
"^3.2.0"
}
}
\ No newline at end of file
extensions/git/src/commands.ts
浏览文件 @
d1b9a70d
...
...
@@ -127,6 +127,15 @@ function command(commandId: string, options: CommandOptions = {}): Function {
};
}
const
ImageMimetypes
=
[
'
image/png
'
,
'
image/gif
'
,
'
image/jpeg
'
,
'
image/webp
'
,
'
image/tiff
'
,
'
image/bmp
'
];
export
class
CommandCenter
{
private
disposables
:
Disposable
[];
...
...
@@ -159,8 +168,8 @@ export class CommandCenter {
}
private
async
_openResource
(
resource
:
Resource
,
preview
?:
boolean
,
preserveFocus
?:
boolean
,
preserveSelection
?:
boolean
):
Promise
<
void
>
{
const
left
=
this
.
getLeftResource
(
resource
);
const
right
=
this
.
getRightResource
(
resource
);
const
left
=
await
this
.
getLeftResource
(
resource
);
const
right
=
await
this
.
getRightResource
(
resource
);
const
title
=
this
.
getTitle
(
resource
);
if
(
!
right
)
{
...
...
@@ -184,56 +193,70 @@ export class CommandCenter {
}
if
(
!
left
)
{
if
(
right
.
scheme
===
'
git
'
)
{
const
repository
=
this
.
model
.
getRepository
(
right
);
await
commands
.
executeCommand
<
void
>
(
'
vscode.open
'
,
right
,
opts
);
}
else
{
await
commands
.
executeCommand
<
void
>
(
'
vscode.diff
'
,
left
,
right
,
title
,
opts
);
}
}
if
(
repository
)
{
const
{
path
,
ref
}
=
fromGitUri
(
right
);
private
async
getURI
(
uri
:
Uri
,
ref
:
string
):
Promise
<
Uri
|
undefined
>
{
const
repository
=
this
.
model
.
getRepository
(
uri
);
if
(
/png$/i
.
test
(
path
)
)
{
const
contents
=
await
repository
.
buffer
(
ref
,
path
);
const
uri
=
Uri
.
parse
(
`data:image/png;label:
${
'
Label
'
}
;description:
${
'
Description
'
}
;base64,
${
contents
.
toString
(
'
base64
'
)}
`
);
// TODO@JOao
if
(
!
repository
)
{
return
toGitUri
(
uri
,
ref
);
}
await
commands
.
executeCommand
<
void
>
(
'
vscode.open
'
,
uri
,
opts
);
return
;
try
{
const
{
size
,
object
}
=
await
repository
.
lstree
(
ref
,
uri
.
fsPath
);
if
(
size
>
5000000
)
{
// 5 MB
return
Uri
.
parse
(
`data:;label:
${
path
.
basename
(
uri
.
fsPath
)}
;description:
${
ref
}
,`
);
}
const
{
mimetype
,
encoding
}
=
await
repository
.
detectObjectType
(
object
);
if
(
mimetype
===
'
text/plain
'
)
{
return
toGitUri
(
uri
,
ref
);
}
if
(
ImageMimetypes
.
indexOf
(
mimetype
)
>
-
1
)
{
const
contents
=
await
repository
.
buffer
(
ref
,
uri
.
fsPath
);
return
Uri
.
parse
(
`data:
${
mimetype
}
;label:
${
path
.
basename
(
uri
.
fsPath
)}
;description:
${
ref
}
;size:
${
size
}
;base64,
${
contents
.
toString
(
'
base64
'
)}
`
);
}
await
commands
.
executeCommand
<
void
>
(
'
vscode.open
'
,
right
,
opts
);
return
Uri
.
parse
(
`data:;label:
${
path
.
basename
(
uri
.
fsPath
)}
;description:
${
ref
}
,`
);
return
;
}
catch
(
err
)
{
return
toGitUri
(
uri
,
ref
);
}
return
await
commands
.
executeCommand
<
void
>
(
'
vscode.diff
'
,
left
,
right
,
title
,
opts
);
}
private
getLeftResource
(
resource
:
Resource
):
Uri
|
undefined
{
private
async
getLeftResource
(
resource
:
Resource
):
Promise
<
Uri
|
undefined
>
{
switch
(
resource
.
type
)
{
case
Status
.
INDEX_MODIFIED
:
case
Status
.
INDEX_RENAMED
:
return
t
oGitUri
(
resource
.
original
,
'
HEAD
'
);
return
t
his
.
getURI
(
resource
.
original
,
'
HEAD
'
);
case
Status
.
MODIFIED
:
return
t
oGitUri
(
resource
.
resourceUri
,
'
~
'
);
return
t
his
.
getURI
(
resource
.
resourceUri
,
'
~
'
);
case
Status
.
DELETED_BY_THEM
:
return
t
oGitUri
(
resource
.
resourceUri
,
''
);
return
t
his
.
getURI
(
resource
.
resourceUri
,
''
);
}
}
private
getRightResource
(
resource
:
Resource
):
Uri
|
undefined
{
private
async
getRightResource
(
resource
:
Resource
):
Promise
<
Uri
|
undefined
>
{
switch
(
resource
.
type
)
{
case
Status
.
INDEX_MODIFIED
:
case
Status
.
INDEX_ADDED
:
case
Status
.
INDEX_COPIED
:
case
Status
.
INDEX_RENAMED
:
return
t
oGitUri
(
resource
.
resourceUri
,
''
);
return
t
his
.
getURI
(
resource
.
resourceUri
,
''
);
case
Status
.
INDEX_DELETED
:
case
Status
.
DELETED_BY_THEM
:
case
Status
.
DELETED
:
return
t
oGitUri
(
resource
.
resourceUri
,
'
HEAD
'
);
return
t
his
.
getURI
(
resource
.
resourceUri
,
'
HEAD
'
);
case
Status
.
MODIFIED
:
case
Status
.
UNTRACKED
:
...
...
extensions/git/src/git.ts
浏览文件 @
d1b9a70d
...
...
@@ -11,7 +11,8 @@ import * as os from 'os';
import
*
as
cp
from
'
child_process
'
;
import
{
EventEmitter
}
from
'
events
'
;
import
iconv
=
require
(
'
iconv-lite
'
);
import
{
assign
,
uniqBy
,
groupBy
,
denodeify
,
IDisposable
,
toDisposable
,
dispose
,
mkdirp
}
from
'
./util
'
;
import
*
as
filetype
from
'
file-type
'
;
import
{
assign
,
uniqBy
,
groupBy
,
denodeify
,
IDisposable
,
toDisposable
,
dispose
,
mkdirp
,
readBytes
,
detectUnicodeEncoding
,
Encoding
}
from
'
./util
'
;
const
readfile
=
denodeify
<
string
>
(
fs
.
readFile
);
...
...
@@ -569,6 +570,59 @@ export class Repository {
return
stdout
;
}
async
lstree
(
treeish
:
string
,
path
:
string
):
Promise
<
{
mode
:
number
,
type
:
string
,
object
:
string
,
size
:
number
}
>
{
const
{
stdout
}
=
await
this
.
run
([
'
ls-tree
'
,
'
-l
'
,
treeish
,
'
--
'
,
path
]);
const
match
=
/^
(\d
+
)\s
+
(\w
+
)\s
+
([
0-9a-f
]{40})\s
+
(\d
+
)
/
.
exec
(
stdout
);
if
(
!
match
)
{
throw
new
GitError
({
message
:
'
Error running ls-tree
'
});
}
const
[,
mode
,
type
,
object
,
size
]
=
match
;
return
{
mode
:
parseInt
(
mode
),
type
,
object
,
size
:
parseInt
(
size
)
};
}
async
detectObjectType
(
object
:
string
):
Promise
<
{
mimetype
:
string
,
encoding
?:
string
}
>
{
const
child
=
await
this
.
stream
([
'
show
'
,
object
]);
const
buffer
=
await
readBytes
(
child
.
stdout
,
4100
);
try
{
child
.
kill
();
}
catch
(
err
)
{
// noop
}
const
encoding
=
detectUnicodeEncoding
(
buffer
);
let
isText
=
true
;
if
(
encoding
!==
Encoding
.
UTF16be
&&
encoding
!==
Encoding
.
UTF16le
)
{
for
(
let
i
=
0
;
i
<
buffer
.
length
;
i
++
)
{
if
(
buffer
.
readInt8
(
i
)
===
0
)
{
isText
=
false
;
break
;
}
}
}
if
(
!
isText
)
{
const
result
=
filetype
(
buffer
);
if
(
!
result
)
{
return
{
mimetype
:
'
application/octet-stream
'
};
}
else
{
return
{
mimetype
:
result
.
mime
};
}
}
if
(
encoding
)
{
return
{
mimetype
:
'
text/plain
'
,
encoding
};
}
else
{
// TODO@JOAO: read the setting OUTSIDE!
return
{
mimetype
:
'
text/plain
'
};
}
}
async
add
(
paths
:
string
[]):
Promise
<
void
>
{
const
args
=
[
'
add
'
,
'
-A
'
,
'
--
'
];
...
...
extensions/git/src/repository.ts
浏览文件 @
d1b9a70d
...
...
@@ -300,7 +300,8 @@ export enum Operation {
Ignore
=
'
Ignore
'
,
Tag
=
'
Tag
'
,
Stash
=
'
Stash
'
,
CheckIgnore
=
'
CheckIgnore
'
CheckIgnore
=
'
CheckIgnore
'
,
LSTree
=
'
LSTree
'
}
function
isReadOnly
(
operation
:
Operation
):
boolean
{
...
...
@@ -308,6 +309,7 @@ function isReadOnly(operation: Operation): boolean {
case
Operation
.
Show
:
case
Operation
.
GetCommitTemplate
:
case
Operation
.
CheckIgnore
:
case
Operation
.
LSTree
:
return
true
;
default
:
return
false
;
...
...
@@ -318,6 +320,8 @@ function shouldShowProgress(operation: Operation): boolean {
switch
(
operation
)
{
case
Operation
.
Fetch
:
case
Operation
.
CheckIgnore
:
case
Operation
.
LSTree
:
case
Operation
.
Show
:
return
false
;
default
:
return
true
;
...
...
@@ -679,6 +683,7 @@ export class Repository implements Disposable {
const
configFiles
=
workspace
.
getConfiguration
(
'
files
'
,
Uri
.
file
(
filePath
));
const
encoding
=
configFiles
.
get
<
string
>
(
'
encoding
'
);
// TODO@joao: Resource config api
return
await
this
.
repository
.
bufferString
(
`
${
ref
}
:
${
relativePath
}
`
,
encoding
);
});
}
...
...
@@ -687,11 +692,21 @@ export class Repository implements Disposable {
return
await
this
.
run
(
Operation
.
Show
,
async
()
=>
{
const
relativePath
=
path
.
relative
(
this
.
repository
.
root
,
filePath
).
replace
(
/
\\
/g
,
'
/
'
);
const
configFiles
=
workspace
.
getConfiguration
(
'
files
'
,
Uri
.
file
(
filePath
));
const
encoding
=
configFiles
.
get
<
string
>
(
'
encoding
'
);
// TODO@joao: REsource config api
return
await
this
.
repository
.
buffer
(
`
${
ref
}
:
${
relativePath
}
`
);
});
}
lstree
(
ref
:
string
,
filePath
:
string
):
Promise
<
{
mode
:
number
,
type
:
string
,
object
:
string
,
size
:
number
}
>
{
return
this
.
run
(
Operation
.
LSTree
,
()
=>
this
.
repository
.
lstree
(
ref
,
filePath
));
}
detectObjectType
(
object
:
string
):
Promise
<
{
mimetype
:
string
,
encoding
?:
string
}
>
{
return
this
.
run
(
Operation
.
Show
,
()
=>
this
.
repository
.
detectObjectType
(
object
));
}
async
getStashes
():
Promise
<
Stash
[]
>
{
return
await
this
.
repository
.
getStashes
();
}
...
...
extensions/git/src/util.ts
浏览文件 @
d1b9a70d
...
...
@@ -7,6 +7,7 @@
import
{
Event
}
from
'
vscode
'
;
import
{
dirname
}
from
'
path
'
;
import
{
Readable
}
from
'
stream
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
byline
from
'
byline
'
;
...
...
@@ -206,3 +207,70 @@ export async function grep(filename: string, pattern: RegExp): Promise<boolean>
stream
.
on
(
'
end
'
,
()
=>
c
(
false
));
});
}
export
function
readBytes
(
stream
:
Readable
,
bytes
:
number
):
Promise
<
Buffer
>
{
return
new
Promise
<
Buffer
>
((
complete
,
error
)
=>
{
let
done
=
false
;
let
buffer
=
new
Buffer
(
bytes
);
let
bytesRead
=
0
;
stream
.
on
(
'
data
'
,
(
data
:
Buffer
)
=>
{
let
bytesToRead
=
Math
.
min
(
bytes
-
bytesRead
,
data
.
length
);
data
.
copy
(
buffer
,
bytesRead
,
0
,
bytesToRead
);
bytesRead
+=
bytesToRead
;
if
(
bytesRead
===
bytes
)
{
(
stream
as
any
).
destroy
();
// Will trigger the close event eventually
}
});
stream
.
on
(
'
error
'
,
(
e
:
Error
)
=>
{
if
(
!
done
)
{
done
=
true
;
error
(
e
);
}
});
stream
.
on
(
'
close
'
,
()
=>
{
if
(
!
done
)
{
done
=
true
;
complete
(
buffer
.
slice
(
0
,
bytesRead
));
}
});
});
}
export
enum
Encoding
{
UTF8
=
'
utf8
'
,
UTF16be
=
'
utf16be
'
,
UTF16le
=
'
utf16le
'
}
export
function
detectUnicodeEncoding
(
buffer
:
Buffer
):
Encoding
|
null
{
if
(
buffer
.
length
<
2
)
{
return
null
;
}
const
b0
=
buffer
.
readUInt8
(
0
);
const
b1
=
buffer
.
readUInt8
(
1
);
if
(
b0
===
0xFE
&&
b1
===
0xFF
)
{
return
Encoding
.
UTF16be
;
}
if
(
b0
===
0xFF
&&
b1
===
0xFE
)
{
return
Encoding
.
UTF16le
;
}
if
(
buffer
.
length
<
3
)
{
return
null
;
}
const
b2
=
buffer
.
readUInt8
(
2
);
if
(
b0
===
0xEF
&&
b1
===
0xBB
&&
b2
===
0xBF
)
{
return
Encoding
.
UTF8
;
}
return
null
;
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录