Merge pull request #1404 from wqweto/develop
Allow space and/or percent in file and directory names
This commit is contained in:
commit
eedac73229
7 changed files with 52 additions and 41 deletions
|
@ -87,7 +87,7 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
|
|
||||||
leftLine, rightLine int
|
leftLine, rightLine int
|
||||||
isTooLong bool
|
isTooLong bool
|
||||||
// FIXME: use first 30 lines to detect file encoding. Should use cache in the future.
|
// FIXME: Should use cache in the future.
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -106,16 +106,10 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
|
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
// FIXME: use first 30 lines to detect file encoding.
|
|
||||||
if i <= 30 {
|
|
||||||
buf.WriteString(line)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Diff data too large, we only show the first about maxlines lines
|
// Diff data too large, we only show the first about maxlines lines
|
||||||
if i == maxlines {
|
if i == maxlines {
|
||||||
isTooLong = true
|
isTooLong = true
|
||||||
log.Warn("Diff data too large")
|
log.Warn("Diff data too large")
|
||||||
//return &Diff{}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -127,7 +121,7 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
continue
|
continue
|
||||||
case line[0] == '@':
|
case line[0] == '@':
|
||||||
if isTooLong {
|
if isTooLong {
|
||||||
return diff, nil
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
curSection = &DiffSection{}
|
curSection = &DiffSection{}
|
||||||
|
@ -137,9 +131,14 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
curSection.Lines = append(curSection.Lines, diffLine)
|
curSection.Lines = append(curSection.Lines, diffLine)
|
||||||
|
|
||||||
// Parse line number.
|
// Parse line number.
|
||||||
ranges := strings.Split(ss[len(ss)-2][1:], " ")
|
ranges := strings.Split(ss[1][1:], " ")
|
||||||
leftLine, _ = com.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int()
|
leftLine, _ = com.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int()
|
||||||
rightLine, _ = com.StrTo(strings.Split(ranges[1], ",")[0]).Int()
|
if len(ranges) > 1 {
|
||||||
|
rightLine, _ = com.StrTo(strings.Split(ranges[1], ",")[0]).Int()
|
||||||
|
} else {
|
||||||
|
log.Warn("Parse line number failed: %v", line)
|
||||||
|
rightLine = leftLine
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
case line[0] == '+':
|
case line[0] == '+':
|
||||||
curFile.Addition++
|
curFile.Addition++
|
||||||
|
@ -164,11 +163,11 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
// Get new file.
|
// Get new file.
|
||||||
if strings.HasPrefix(line, DIFF_HEAD) {
|
if strings.HasPrefix(line, DIFF_HEAD) {
|
||||||
if isTooLong {
|
if isTooLong {
|
||||||
return diff, nil
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
fs := strings.Split(line[len(DIFF_HEAD):], " ")
|
beg := len(DIFF_HEAD)
|
||||||
a := fs[0]
|
a := line[beg : (len(line)-beg)/2+beg]
|
||||||
|
|
||||||
curFile = &DiffFile{
|
curFile = &DiffFile{
|
||||||
Name: a[strings.Index(a, "/")+1:],
|
Name: a[strings.Index(a, "/")+1:],
|
||||||
|
@ -201,14 +200,19 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use first 30 lines to detect file encoding.
|
for _, f := range diff.Files {
|
||||||
charsetLabel, err := base.DetectEncoding(buf.Bytes())
|
buf.Reset()
|
||||||
if charsetLabel != "utf8" && err == nil {
|
for _, sec := range f.Sections {
|
||||||
encoding, _ := charset.Lookup(charsetLabel)
|
for _, l := range sec.Lines {
|
||||||
|
buf.WriteString(l.Content)
|
||||||
if encoding != nil {
|
buf.WriteString("\n")
|
||||||
d := encoding.NewDecoder()
|
}
|
||||||
for _, f := range diff.Files {
|
}
|
||||||
|
charsetLabel, err := base.DetectEncoding(buf.Bytes())
|
||||||
|
if charsetLabel != "UTF-8" && err == nil {
|
||||||
|
encoding, _ := charset.Lookup(charsetLabel)
|
||||||
|
if encoding != nil {
|
||||||
|
d := encoding.NewDecoder()
|
||||||
for _, sec := range f.Sections {
|
for _, sec := range f.Sections {
|
||||||
for _, l := range sec.Lines {
|
for _, l := range sec.Lines {
|
||||||
if c, _, err := transform.String(d, l.Content); err == nil {
|
if c, _, err := transform.String(d, l.Content); err == nil {
|
||||||
|
@ -219,7 +223,6 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff, nil
|
return diff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ func ShortSha(sha1 string) string {
|
||||||
func DetectEncoding(content []byte) (string, error) {
|
func DetectEncoding(content []byte) (string, error) {
|
||||||
detector := chardet.NewTextDetector()
|
detector := chardet.NewTextDetector()
|
||||||
result, err := detector.DetectBest(content)
|
result, err := detector.DetectBest(content)
|
||||||
if result.Charset == "ISO-8859-1" {
|
if result.Charset != "UTF-8" && len(setting.AnsiCharset) > 0 {
|
||||||
return setting.AnsiCharset, err
|
return setting.AnsiCharset, err
|
||||||
}
|
}
|
||||||
return result.Charset, err
|
return result.Charset, err
|
||||||
|
@ -67,7 +67,7 @@ func ToUtf8WithErr(content []byte) (error, string) {
|
||||||
return err, ""
|
return err, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if charsetLabel == "utf8" {
|
if charsetLabel == "UTF-8" {
|
||||||
return nil, string(content)
|
return nil, string(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -313,7 +313,7 @@ func NewConfigContext() {
|
||||||
RepoRootPath = path.Clean(RepoRootPath)
|
RepoRootPath = path.Clean(RepoRootPath)
|
||||||
}
|
}
|
||||||
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
|
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
|
||||||
AnsiCharset = sec.Key("ANSI_CHARSET").MustString("ISO-8859-1")
|
AnsiCharset = sec.Key("ANSI_CHARSET").MustString("")
|
||||||
|
|
||||||
// UI settings.
|
// UI settings.
|
||||||
IssuePagingNum = Cfg.Section("ui").Key("ISSUE_PAGING_NUM").MustInt(10)
|
IssuePagingNum = Cfg.Section("ui").Key("ISSUE_PAGING_NUM").MustInt(10)
|
||||||
|
|
|
@ -26,10 +26,17 @@ func ServeBlob(ctx *middleware.Context, blob *git.Blob) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, isTextFile := base.IsTextFile(buf)
|
_, isTextFile := base.IsTextFile(buf)
|
||||||
_, isImageFile := base.IsImageFile(buf)
|
if isTextFile {
|
||||||
if !isTextFile && !isImageFile {
|
charset, _ := base.DetectEncoding(buf)
|
||||||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+path.Base(ctx.Repo.TreeName))
|
if charset != "UTF-8" {
|
||||||
ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
|
ctx.Resp.Header().Set("Content-Type", "text/plain; charset="+charset)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, isImageFile := base.IsImageFile(buf)
|
||||||
|
if !isImageFile {
|
||||||
|
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+path.Base(ctx.Repo.TreeName))
|
||||||
|
ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctx.Resp.Write(buf)
|
ctx.Resp.Write(buf)
|
||||||
_, err = io.Copy(ctx.Resp, dataRc)
|
_, err = io.Copy(ctx.Resp, dataRc)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{{if .IsDiffCompare }}
|
{{if .IsDiffCompare }}
|
||||||
<div class="panel panel-info panel-radius compare-head-box">
|
<div class="panel panel-info panel-radius compare-head-box">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<a class="pull-right btn btn-blue btn-header btn-medium btn-radius" rel="nofollow" href="{{.SourcePath}}">{{.i18n.Tr "repo.diff.browse_source"}}</a>
|
<a class="pull-right btn btn-blue btn-header btn-medium btn-radius" rel="nofollow" href="{{EscapePound .SourcePath}}">{{.i18n.Tr "repo.diff.browse_source"}}</a>
|
||||||
<h4><a href="{{$.RepoLink}}/commit/{{.BeforeCommitId}}" class="label label-green">{{ShortSha .BeforeCommitId}}</a> ... <a href="{{$.RepoLink}}/commit/{{.AfterCommitId}}" class="label label-green">{{ShortSha .AfterCommitId}}</a></h4>
|
<h4><a href="{{$.RepoLink}}/commit/{{.BeforeCommitId}}" class="label label-green">{{ShortSha .BeforeCommitId}}</a> ... <a href="{{$.RepoLink}}/commit/{{.AfterCommitId}}" class="label label-green">{{ShortSha .AfterCommitId}}</a></h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body compare">
|
<div class="panel-body compare">
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="panel panel-info panel-radius diff-head-box">
|
<div class="panel panel-info panel-radius diff-head-box">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<a class="pull-right btn btn-blue btn-header btn-medium btn-radius" rel="nofollow" href="{{.SourcePath}}">{{.i18n.Tr "repo.diff.browse_source"}}</a>
|
<a class="pull-right btn btn-blue btn-header btn-medium btn-radius" rel="nofollow" href="{{EscapePound .SourcePath}}">{{.i18n.Tr "repo.diff.browse_source"}}</a>
|
||||||
<h4 class="commit-message">{{RenderCommitMessage .Commit.Message $.RepoLink}}</h4>
|
<h4 class="commit-message">{{RenderCommitMessage .Commit.Message $.RepoLink}}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<img class="avatar-30" src="{{AvatarLink .Commit.Author.Email}}" />
|
<img class="avatar-30" src="{{AvatarLink .Commit.Author.Email}}" />
|
||||||
<strong>{{.Commit.Author.Name}}</strong>
|
<strong>{{.Commit.Author.Name}}</strong>
|
||||||
{{end}}
|
{{end}}
|
||||||
<span class="text-grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span>
|
<span class="text-grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,9 +90,9 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{if $file.IsDeleted}}
|
{{if $file.IsDeleted}}
|
||||||
<a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{$.BeforeSourcePath}}/{{.Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
|
<a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{$.SourcePath}}/{{.Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
|
<a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<span class="file">{{$file.Name}}</span>
|
<span class="file">{{$file.Name}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,7 +100,7 @@
|
||||||
<div class="panel-body file-body file-code code-view code-diff">
|
<div class="panel-body file-body file-code code-view code-diff">
|
||||||
{{if $isImage}}
|
{{if $isImage}}
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<img src="{{$.RawPath}}/{{.Name}}">
|
<img src="{{$.RawPath}}/{{EscapePound .Name}}">
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<table>
|
<table>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
<td class="lines-num lines-num-new">
|
<td class="lines-num lines-num-new">
|
||||||
<span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span>
|
<span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="lines-code">
|
<td class="lines-code">
|
||||||
<pre>{{$line.Content}}</pre>
|
<pre>{{$line.Content}}</pre>
|
||||||
</td>
|
</td>
|
||||||
|
@ -126,7 +126,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -50,7 +50,8 @@
|
||||||
{{if eq $i $l}}
|
{{if eq $i $l}}
|
||||||
<span class="bread">{{$v}}</span>
|
<span class="bread">{{$v}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="bread"><a href="{{EscapePound $.BranchLink}}/{{index $.Paths $i}}">{{$v}}</a></span>
|
{{ $p := index $.Paths $i}}
|
||||||
|
<span class="bread"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}">{{$v}}</a></span>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if not .ReadmeInList}}
|
{{if not .ReadmeInList}}
|
||||||
{{if not .IsCommit}}
|
{{if not .IsCommit}}
|
||||||
<a class="right" href="{{.RepoLink}}/src/{{.CommitId}}/{{.TreeName}}">
|
<a class="right" href="{{.RepoLink}}/src/{{.CommitId}}/{{EscapePound .TreeName}}">
|
||||||
<button class="btn btn-medium btn-gray btn-right-radius btn-comb">{{.i18n.Tr "repo.file_permalink"}}</button>
|
<button class="btn btn-medium btn-gray btn-right-radius btn-comb">{{.i18n.Tr "repo.file_permalink"}}</button>
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<a class="right" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}/{{.TreeName}}">
|
<a class="right" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}/{{EscapePound .TreeName}}">
|
||||||
<button class="btn btn-medium btn-gray btn-right-radius btn-comb">{{.i18n.Tr "repo.file_history"}}</button>
|
<button class="btn btn-medium btn-gray btn-right-radius btn-comb">{{.i18n.Tr "repo.file_history"}}</button>
|
||||||
</a>
|
</a>
|
||||||
<a class="right" href="{{EscapePound .FileLink}}">
|
<a class="right" href="{{EscapePound .FileLink}}">
|
||||||
|
@ -47,4 +47,4 @@
|
||||||
</table>
|
</table>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Reference in a new issue