aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gogs.go2
-rw-r--r--models/git_diff.go445
-rw-r--r--models/git_diff_test.go16
-rw-r--r--routers/repo/commit.go6
-rw-r--r--templates/.VERSION2
-rw-r--r--templates/repo/diff/box.tmpl8
-rw-r--r--templates/repo/diff/section_unified.tmpl4
-rw-r--r--vendor/github.com/gogits/git-module/commit.go12
-rw-r--r--vendor/github.com/gogits/git-module/git.go2
-rw-r--r--vendor/github.com/gogits/git-module/repo_diff.go398
-rw-r--r--vendor/vendor.json6
11 files changed, 490 insertions, 411 deletions
diff --git a/gogs.go b/gogs.go
index a3d9c3a1..63945494 100644
--- a/gogs.go
+++ b/gogs.go
@@ -16,7 +16,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-const APP_VER = "0.11.1.0403"
+const APP_VER = "0.11.2.0404"
func init() {
setting.AppVer = APP_VER
diff --git a/models/git_diff.go b/models/git_diff.go
index 00549119..7af7ee83 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -5,63 +5,25 @@
package models
import (
- "bufio"
"bytes"
"fmt"
"html"
"html/template"
"io"
- "io/ioutil"
- "os"
- "os/exec"
- "strings"
- "github.com/Unknwon/com"
"github.com/sergi/go-diff/diffmatchpatch"
"golang.org/x/net/html/charset"
"golang.org/x/text/transform"
- log "gopkg.in/clog.v1"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/base"
- "github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/template/highlight"
)
-type DiffLineType uint8
-
-const (
- DIFF_LINE_PLAIN DiffLineType = iota + 1
- DIFF_LINE_ADD
- DIFF_LINE_DEL
- DIFF_LINE_SECTION
-)
-
-type DiffFileType uint8
-
-const (
- DIFF_FILE_ADD DiffFileType = iota + 1
- DIFF_FILE_CHANGE
- DIFF_FILE_DEL
- DIFF_FILE_RENAME
-)
-
-type DiffLine struct {
- LeftIdx int
- RightIdx int
- Type DiffLineType
- Content string
-}
-
-func (d *DiffLine) GetType() int {
- return int(d.Type)
-}
-
type DiffSection struct {
- Name string
- Lines []*DiffLine
+ *git.DiffSection
}
var (
@@ -70,24 +32,24 @@ var (
codeTagSuffix = []byte("</span>")
)
-func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {
+func diffToHTML(diffs []diffmatchpatch.Diff, lineType git.DiffLineType) template.HTML {
buf := bytes.NewBuffer(nil)
// Reproduce signs which are cutted for inline diff before.
switch lineType {
- case DIFF_LINE_ADD:
+ case git.DIFF_LINE_ADD:
buf.WriteByte('+')
- case DIFF_LINE_DEL:
+ case git.DIFF_LINE_DEL:
buf.WriteByte('-')
}
for i := range diffs {
switch {
- case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DIFF_LINE_ADD:
+ case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == git.DIFF_LINE_ADD:
buf.Write(addedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
- case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DIFF_LINE_DEL:
+ case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == git.DIFF_LINE_DEL:
buf.Write(removedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
@@ -99,77 +61,34 @@ func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTM
return template.HTML(buf.Bytes())
}
-// get an specific line by type (add or del) and file line number
-func (diffSection *DiffSection) GetLine(lineType DiffLineType, idx int) *DiffLine {
- var (
- difference = 0
- addCount = 0
- delCount = 0
- matchDiffLine *DiffLine
- )
-
-LOOP:
- for _, diffLine := range diffSection.Lines {
- switch diffLine.Type {
- case DIFF_LINE_ADD:
- addCount++
- case DIFF_LINE_DEL:
- delCount++
- default:
- if matchDiffLine != nil {
- break LOOP
- }
- difference = diffLine.RightIdx - diffLine.LeftIdx
- addCount = 0
- delCount = 0
- }
-
- switch lineType {
- case DIFF_LINE_DEL:
- if diffLine.RightIdx == 0 && diffLine.LeftIdx == idx-difference {
- matchDiffLine = diffLine
- }
- case DIFF_LINE_ADD:
- if diffLine.LeftIdx == 0 && diffLine.RightIdx == idx+difference {
- matchDiffLine = diffLine
- }
- }
- }
-
- if addCount == delCount {
- return matchDiffLine
- }
- return nil
-}
-
var diffMatchPatch = diffmatchpatch.New()
func init() {
diffMatchPatch.DiffEditCost = 100
}
-// computes inline diff for the given line
-func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML {
+// ComputedInlineDiffFor computes inline diff for the given line.
+func (diffSection *DiffSection) ComputedInlineDiffFor(diffLine *git.DiffLine) template.HTML {
if setting.Git.DisableDiffHighlight {
return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
var (
- compareDiffLine *DiffLine
+ compareDiffLine *git.DiffLine
diff1 string
diff2 string
)
// try to find equivalent diff line. ignore, otherwise
switch diffLine.Type {
- case DIFF_LINE_ADD:
- compareDiffLine = diffSection.GetLine(DIFF_LINE_DEL, diffLine.RightIdx)
+ case git.DIFF_LINE_ADD:
+ compareDiffLine = diffSection.Line(git.DIFF_LINE_DEL, diffLine.RightIdx)
if compareDiffLine == nil {
return template.HTML(html.EscapeString(diffLine.Content))
}
diff1 = compareDiffLine.Content
diff2 = diffLine.Content
- case DIFF_LINE_DEL:
- compareDiffLine = diffSection.GetLine(DIFF_LINE_ADD, diffLine.LeftIdx)
+ case git.DIFF_LINE_DEL:
+ compareDiffLine = diffSection.Line(git.DIFF_LINE_ADD, diffLine.LeftIdx)
if compareDiffLine == nil {
return template.HTML(html.EscapeString(diffLine.Content))
}
@@ -186,336 +105,90 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem
}
type DiffFile struct {
- Name string
- OldName string
- Index string // 40-byte SHA, Changed/New: new SHA; Deleted: old SHA
- Addition, Deletion int
- Type DiffFileType
- IsCreated bool
- IsDeleted bool
- IsBin bool
- IsRenamed bool
- IsSubmodule bool
- Sections []*DiffSection
- IsIncomplete bool
+ *git.DiffFile
+ Sections []*DiffSection
}
-func (diffFile *DiffFile) GetType() int {
- return int(diffFile.Type)
-}
-
-func (diffFile *DiffFile) GetHighlightClass() string {
+func (diffFile *DiffFile) HighlightClass() string {
return highlight.FileNameToHighlightClass(diffFile.Name)
}
type Diff struct {
- TotalAddition, TotalDeletion int
- Files []*DiffFile
- IsIncomplete bool
-}
-
-func (diff *Diff) NumFiles() int {
- return len(diff.Files)
+ *git.Diff
+ Files []*DiffFile
}
-const DIFF_HEAD = "diff --git "
-
-// TODO: move this function to gogits/git-module
-func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*Diff, error) {
- var (
- diff = &Diff{Files: make([]*DiffFile, 0)}
-
- curFile *DiffFile
- curSection = &DiffSection{
- Lines: make([]*DiffLine, 0, 10),
- }
-
- leftLine, rightLine int
- lineCount int
- curFileLinesCount int
- )
-
- input := bufio.NewReader(reader)
- isEOF := false
- for !isEOF {
- line, err := input.ReadString('\n')
- if err != nil {
- if err == io.EOF {
- isEOF = true
- } else {
- return nil, fmt.Errorf("ReadString: %v", err)
- }
- }
-
- if len(line) > 0 && line[len(line)-1] == '\n' {
- // Remove line break.
- line = line[:len(line)-1]
- }
-
- if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 {
- continue
- }
-
- curFileLinesCount++
- lineCount++
-
- // Diff data too large, we only show the first about maxlines lines
- if curFileLinesCount >= maxLines || len(line) >= maxLineCharacteres {
- curFile.IsIncomplete = true
- }
+func NewDiff(gitDiff *git.Diff) *Diff {
+ diff := &Diff{
+ Diff: gitDiff,
+ Files: make([]*DiffFile, gitDiff.NumFiles()),
+ }
- switch {
- case line[0] == ' ':
- diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine}
- leftLine++
- rightLine++
- curSection.Lines = append(curSection.Lines, diffLine)
- continue
- case line[0] == '@':
- curSection = &DiffSection{}
- curFile.Sections = append(curFile.Sections, curSection)
- ss := strings.Split(line, "@@")
- diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line}
- curSection.Lines = append(curSection.Lines, diffLine)
+ // FIXME: detect encoding while parsing.
+ var buf bytes.Buffer
+ for i := range gitDiff.Files {
+ buf.Reset()
- // Parse line number.
- ranges := strings.Split(ss[1][1:], " ")
- leftLine, _ = com.StrTo(strings.Split(ranges[0], ",")[0][1:]).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
- case line[0] == '+':
- curFile.Addition++
- diff.TotalAddition++
- diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine}
- rightLine++
- curSection.Lines = append(curSection.Lines, diffLine)
- continue
- case line[0] == '-':
- curFile.Deletion++
- diff.TotalDeletion++
- diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine}
- if leftLine > 0 {
- leftLine++
- }
- curSection.Lines = append(curSection.Lines, diffLine)
- case strings.HasPrefix(line, "Binary"):
- curFile.IsBin = true
- continue
+ diff.Files[i] = &DiffFile{
+ DiffFile: gitDiff.Files[i],
+ Sections: make([]*DiffSection, gitDiff.Files[i].NumSections()),
}
- // Get new file.
- if strings.HasPrefix(line, DIFF_HEAD) {
- middle := -1
-
- // Note: In case file name is surrounded by double quotes (it happens only in git-shell).
- // e.g. diff --git "a/xxx" "b/xxx"
- hasQuote := line[len(DIFF_HEAD)] == '"'
- if hasQuote {
- middle = strings.Index(line, ` "b/`)
- } else {
- middle = strings.Index(line, " b/")
- }
-
- beg := len(DIFF_HEAD)
- a := line[beg+2 : middle]
- b := line[middle+3:]
- if hasQuote {
- a = string(git.UnescapeChars([]byte(a[1 : len(a)-1])))
- b = string(git.UnescapeChars([]byte(b[1 : len(b)-1])))
+ for j := range gitDiff.Files[i].Sections {
+ diff.Files[i].Sections[j] = &DiffSection{
+ DiffSection: gitDiff.Files[i].Sections[j],
}
- curFile = &DiffFile{
- Name: a,
- Type: DIFF_FILE_CHANGE,
- Sections: make([]*DiffSection, 0, 10),
- }
- diff.Files = append(diff.Files, curFile)
- if len(diff.Files) >= maxFiles {
- diff.IsIncomplete = true
- io.Copy(ioutil.Discard, reader)
- break
- }
- curFileLinesCount = 0
-
- // Check file diff type and submodule.
- CHECK_TYPE:
- for {
- line, err := input.ReadString('\n')
- if err != nil {
- if err == io.EOF {
- isEOF = true
- } else {
- return nil, fmt.Errorf("ReadString: %v", err)
- }
- }
-
- switch {
- case strings.HasPrefix(line, "new file"):
- curFile.Type = DIFF_FILE_ADD
- curFile.IsCreated = true
- curFile.IsSubmodule = strings.HasSuffix(line, " 160000\n")
- case strings.HasPrefix(line, "deleted"):
- curFile.Type = DIFF_FILE_DEL
- curFile.IsDeleted = true
- curFile.IsSubmodule = strings.HasSuffix(line, " 160000\n")
- case strings.HasPrefix(line, "index"):
- if curFile.IsDeleted {
- curFile.Index = line[6:46]
- } else if len(line) >= 88 {
- curFile.Index = line[49:88]
- } else {
- curFile.Index = curFile.Name
- }
- break CHECK_TYPE
- case strings.HasPrefix(line, "similarity index 100%"):
- curFile.Type = DIFF_FILE_RENAME
- curFile.IsRenamed = true
- curFile.OldName = curFile.Name
- curFile.Name = b
- curFile.Index = b
- break CHECK_TYPE
- }
- }
- }
- }
-
- // FIXME: detect encoding while parsing.
- var buf bytes.Buffer
- for _, f := range diff.Files {
- buf.Reset()
- for _, sec := range f.Sections {
- for _, l := range sec.Lines {
- buf.WriteString(l.Content)
+ for k := range diff.Files[i].Sections[j].Lines {
+ buf.WriteString(diff.Files[i].Sections[j].Lines[k].Content)
buf.WriteString("\n")
}
}
+
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 _, l := range sec.Lines {
- if c, _, err := transform.String(d, l.Content); err == nil {
- l.Content = c
+ for j := range diff.Files[i].Sections {
+ for k := range diff.Files[i].Sections[j].Lines {
+ if c, _, err := transform.String(d, diff.Files[i].Sections[j].Lines[k].Content); err == nil {
+ diff.Files[i].Sections[j].Lines[k].Content = c
}
}
}
}
}
}
- return diff, nil
-}
-
-func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
- gitRepo, err := git.OpenRepository(repoPath)
- if err != nil {
- return nil, err
- }
-
- commit, err := gitRepo.GetCommit(afterCommitID)
- if err != nil {
- return nil, err
- }
-
- var cmd *exec.Cmd
- // if "after" commit given
- if len(beforeCommitID) == 0 {
- // First commit of repository.
- if commit.ParentCount() == 0 {
- cmd = exec.Command("git", "show", "--full-index", afterCommitID)
- } else {
- c, _ := commit.Parent(0)
- cmd = exec.Command("git", "diff", "--full-index", "-M", c.ID.String(), afterCommitID)
- }
- } else {
- cmd = exec.Command("git", "diff", "--full-index", "-M", beforeCommitID, afterCommitID)
- }
- cmd.Dir = repoPath
- cmd.Stderr = os.Stderr
- stdout, err := cmd.StdoutPipe()
- if err != nil {
- return nil, fmt.Errorf("StdoutPipe: %v", err)
- }
-
- if err = cmd.Start(); err != nil {
- return nil, fmt.Errorf("Start: %v", err)
- }
+ return diff
+}
- pid := process.Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cmd)
- defer process.Remove(pid)
+func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*Diff, error) {
+ done := make(chan error)
+ var gitDiff *git.Diff
+ go func() {
+ gitDiff = git.ParsePatch(done, maxLines, maxLineCharacteres, maxFiles, reader)
+ }()
- diff, err := ParsePatch(maxLines, maxLineCharacteres, maxFiles, stdout)
- if err != nil {
+ if err := <-done; err != nil {
return nil, fmt.Errorf("ParsePatch: %v", err)
}
-
- if err = cmd.Wait(); err != nil {
- return nil, fmt.Errorf("Wait: %v", err)
- }
-
- return diff, nil
+ return NewDiff(gitDiff), nil
}
-type RawDiffType string
-
-const (
- RAW_DIFF_NORMAL RawDiffType = "diff"
- RAW_DIFF_PATCH RawDiffType = "patch"
-)
-
-// GetRawDiff dumps diff results of repository in given commit ID to io.Writer.
-// TODO: move this function to gogits/git-module
-func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Writer) error {
- repo, err := git.OpenRepository(repoPath)
- if err != nil {
- return fmt.Errorf("OpenRepository: %v", err)
- }
-
- commit, err := repo.GetCommit(commitID)
+func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
+ gitDiff, err := git.GetDiffRange(repoPath, beforeCommitID, afterCommitID, maxLines, maxLineCharacteres, maxFiles)
if err != nil {
- return fmt.Errorf("GetCommit: %v", err)
- }
-
- var cmd *exec.Cmd
- switch diffType {
- case RAW_DIFF_NORMAL:
- if commit.ParentCount() == 0 {
- cmd = exec.Command("git", "show", commitID)
- } else {
- c, _ := commit.Parent(0)
- cmd = exec.Command("git", "diff", "-M", c.ID.String(), commitID)
- }
- case RAW_DIFF_PATCH:
- if commit.ParentCount() == 0 {
- cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", "--root", commitID)
- } else {
- c, _ := commit.Parent(0)
- query := fmt.Sprintf("%s...%s", commitID, c.ID.String())
- cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", query)
- }
- default:
- return fmt.Errorf("invalid diffType: %s", diffType)
+ return nil, fmt.Errorf("GetDiffRange: %v", err)
}
-
- stderr := new(bytes.Buffer)
-
- cmd.Dir = repoPath
- cmd.Stdout = writer
- cmd.Stderr = stderr
-
- if err = cmd.Run(); err != nil {
- return fmt.Errorf("Run: %v - %s", err, stderr)
- }
- return nil
+ return NewDiff(gitDiff), nil
}
func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
- return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacteres, maxFiles)
+ gitDiff, err := git.GetDiffCommit(repoPath, commitID, maxLines, maxLineCharacteres, maxFiles)
+ if err != nil {
+ return nil, fmt.Errorf("GetDiffCommit: %v", err)
+ }
+ return NewDiff(gitDiff), nil
}
diff --git a/models/git_diff_test.go b/models/git_diff_test.go
index 7f390adb..74032371 100644
--- a/models/git_diff_test.go
+++ b/models/git_diff_test.go
@@ -1,9 +1,15 @@
+// Copyright 2016 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
package models
import (
- dmp "github.com/sergi/go-diff/diffmatchpatch"
"html/template"
"testing"
+
+ "github.com/gogits/git-module"
+ dmp "github.com/sergi/go-diff/diffmatchpatch"
)
func assertEqual(t *testing.T, s1 string, s2 template.HTML) {
@@ -12,24 +18,24 @@ func assertEqual(t *testing.T, s1 string, s2 template.HTML) {
}
}
-func assertLineEqual(t *testing.T, d1 *DiffLine, d2 *DiffLine) {
+func assertLineEqual(t *testing.T, d1 *git.DiffLine, d2 *git.DiffLine) {
if d1 != d2 {
t.Errorf("%v should be equal %v", d1, d2)
}
}
-func TestDiffToHTML(t *testing.T) {
+func Test_diffToHTML(t *testing.T) {
assertEqual(t, "+foo <span class=\"added-code\">bar</span> biz", diffToHTML([]dmp.Diff{
dmp.Diff{dmp.DiffEqual, "foo "},
dmp.Diff{dmp.DiffInsert, "bar"},
dmp.Diff{dmp.DiffDelete, " baz"},
dmp.Diff{dmp.DiffEqual, " biz"},
- }, DIFF_LINE_ADD))
+ }, git.DIFF_LINE_ADD))
assertEqual(t, "-foo <span class=\"removed-code\">bar</span> biz", diffToHTML([]dmp.Diff{
dmp.Diff{dmp.DiffEqual, "foo "},
dmp.Diff{dmp.DiffDelete, "bar"},
dmp.Diff{dmp.DiffInsert, " baz"},
dmp.Diff{dmp.DiffEqual, " biz"},
- }, DIFF_LINE_DEL))
+ }, git.DIFF_LINE_DEL))
}
diff --git a/routers/repo/commit.go b/routers/repo/commit.go
index 409cee85..bf03d53e 100644
--- a/routers/repo/commit.go
+++ b/routers/repo/commit.go
@@ -141,7 +141,7 @@ func Diff(ctx *context.Context) {
commitID, setting.Git.MaxGitDiffLines,
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
if err != nil {
- ctx.Handle(404, "GetDiffCommit", err)
+ ctx.NotFoundOrServerError("GetDiffCommit", git.IsErrNotExist, err)
return
}
@@ -180,10 +180,10 @@ func Diff(ctx *context.Context) {
}
func RawDiff(ctx *context.Context) {
- if err := models.GetRawDiff(
+ if err := git.GetRawDiff(
models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name),
ctx.Params(":sha"),
- models.RawDiffType(ctx.Params(":ext")),
+ git.RawDiffType(ctx.Params(":ext")),
ctx.Resp,
); err != nil {
ctx.Handle(500, "GetRawDiff", err)
diff --git a/templates/.VERSION b/templates/.VERSION
index 9102c746..d4ec5cbc 100644
--- a/templates/.VERSION
+++ b/templates/.VERSION
@@ -1 +1 @@
-0.11.1.0403 \ No newline at end of file
+0.11.2.0404 \ No newline at end of file
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl
index 89e46e80..78237877 100644
--- a/templates/repo/diff/box.tmpl
+++ b/templates/repo/diff/box.tmpl
@@ -89,27 +89,27 @@
<table>
<tbody>
{{if $.IsSplitStyle}}
- {{$highlightClass := $file.GetHighlightClass}}
+ {{$highlightClass := $file.HighlightClass}}
{{range $j, $section := $file.Sections}}
{{range $k, $line := $section.Lines}}
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
{{if eq .GetType 4}}
<td class="lines-num"></td>
<td colspan="3" class="lines-code">
- <pre><code class="{{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</code></pre>
+ <pre><code class="{{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{$section.ComputedInlineDiffFor $line}}</code></pre>
</td>
{{else}}
<td class="lines-num lines-num-old">
<span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span>
</td>
<td class="lines-code halfwidth">
- <pre><code class="wrap {{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</code></pre>
+ <pre><code class="wrap {{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{if $line.LeftIdx}}{{$section.ComputedInlineDiffFor $line}}{{end}}</code></pre>
</td>
<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>
</td>
<td class="lines-code halfwidth">
- <pre><code class="wrap {{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</code></pre>
+ <pre><code class="wrap {{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{if $line.RightIdx}}{{$section.ComputedInlineDiffFor $line}}{{end}}</code></pre>
</td>
{{end}}
</tr>
diff --git a/templates/repo/diff/section_unified.tmpl b/templates/repo/diff/section_unified.tmpl
index 619f97cf..0832d39f 100644
--- a/templates/repo/diff/section_unified.tmpl
+++ b/templates/repo/diff/section_unified.tmpl
@@ -1,5 +1,5 @@
{{$file := .}}
-{{$highlightClass := $file.GetHighlightClass}}
+{{$highlightClass := $file.HighlightClass}}
{{range $j, $section := $file.Sections}}
{{range $k, $line := $section.Lines}}
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
@@ -20,7 +20,7 @@
</td>
{{end}}
<td class="lines-code">
- <pre><code class="{{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</code></pre>
+ <pre><code class="{{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{$section.ComputedInlineDiffFor $line}}</code></pre>
</td>
</tr>
{{end}}
diff --git a/vendor/github.com/gogits/git-module/commit.go b/vendor/github.com/gogits/git-module/commit.go
index 6cc6b5fd..64831d7f 100644
--- a/vendor/github.com/gogits/git-module/commit.go
+++ b/vendor/github.com/gogits/git-module/commit.go
@@ -271,10 +271,7 @@ func NewCommitFileStatus() *CommitFileStatus {
// GetCommitFileStatus returns file status of commit in given repository.
func GetCommitFileStatus(repoPath, commitID string) (*CommitFileStatus, error) {
stdout, w := io.Pipe()
- defer stdout.Close()
-
- stderr := new(bytes.Buffer)
-
+ done := make(chan struct{})
fileStatus := NewCommitFileStatus()
go func() {
scanner := bufio.NewScanner(stdout)
@@ -293,12 +290,17 @@ func GetCommitFileStatus(repoPath, commitID string) (*CommitFileStatus, error) {
fileStatus.Modified = append(fileStatus.Modified, fields[1])
}
}
+ done <- struct{}{}
}()
- if err := NewCommand("log", "-1", "--name-status", "--pretty=format:''", commitID).RunInDirPipeline(repoPath, w, stderr); err != nil {
+ stderr := new(bytes.Buffer)
+ err := NewCommand("log", "-1", "--name-status", "--pretty=format:''", commitID).RunInDirPipeline(repoPath, w, stderr)
+ w.Close() // Close writer to exit parsing goroutine
+ if err != nil {
return nil, concatenateError(err, stderr.String())
}
+ <-done
return fileStatus, nil
}
diff --git a/vendor/github.com/gogits/git-module/git.go b/vendor/github.com/gogits/git-module/git.go
index 2ba3b1a5..538e66d7 100644
--- a/vendor/github.com/gogits/git-module/git.go
+++ b/vendor/github.com/gogits/git-module/git.go
@@ -10,7 +10,7 @@ import (
"time"
)
-const _VERSION = "0.5.1"
+const _VERSION = "0.6.0"
func Version() string {
return _VERSION
diff --git a/vendor/github.com/gogits/git-module/repo_diff.go b/vendor/github.com/gogits/git-module/repo_diff.go
new file mode 100644
index 00000000..797fb7a0
--- /dev/null
+++ b/vendor/github.com/gogits/git-module/repo_diff.go
@@ -0,0 +1,398 @@
+// Copyright 2017 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package git
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// DiffLineType represents the type of a line in diff.
+type DiffLineType uint8
+
+const (
+ DIFF_LINE_PLAIN DiffLineType = iota + 1
+ DIFF_LINE_ADD
+ DIFF_LINE_DEL
+ DIFF_LINE_SECTION
+)
+
+// DiffFileType represents the file status in diff.
+type DiffFileType uint8
+
+const (
+ DIFF_FILE_ADD DiffFileType = iota + 1
+ DIFF_FILE_CHANGE
+ DIFF_FILE_DEL
+ DIFF_FILE_RENAME
+)
+
+// DiffLine represents a line in diff.
+type DiffLine struct {
+ LeftIdx int
+ RightIdx int
+ Type DiffLineType
+ Content string
+}
+
+func (d *DiffLine) GetType() int {
+ return int(d.Type)
+}
+
+// DiffSection represents a section in diff.
+type DiffSection struct {
+ Name string
+ Lines []*DiffLine
+}
+
+// Line returns a specific line by type (add or del) and file line number from a section.
+func (diffSection *DiffSection) Line(lineType DiffLineType, idx int) *DiffLine {
+ var (
+ difference = 0
+ addCount = 0
+ delCount = 0
+ matchDiffLine *DiffLine
+ )
+
+LOOP:
+ for _, diffLine := range diffSection.Lines {
+ switch diffLine.Type {
+ case DIFF_LINE_ADD:
+ addCount++
+ case DIFF_LINE_DEL:
+ delCount++
+ default:
+ if matchDiffLine != nil {
+ break LOOP
+ }
+ difference = diffLine.RightIdx - diffLine.LeftIdx
+ addCount = 0
+ delCount = 0
+ }
+
+ switch lineType {
+ case DIFF_LINE_DEL:
+ if diffLine.RightIdx == 0 && diffLine.LeftIdx == idx-difference {
+ matchDiffLine = diffLine
+ }
+ case DIFF_LINE_ADD:
+ if diffLine.LeftIdx == 0 && diffLine.RightIdx == idx+difference {
+ matchDiffLine = diffLine
+ }
+ }
+ }
+
+ if addCount == delCount {
+ return matchDiffLine
+ }
+ return nil
+}
+
+// DiffFile represents a file in diff.
+type DiffFile struct {
+ Name string
+ OldName string
+ Index string // 40-byte SHA, Changed/New: new SHA; Deleted: old SHA
+ Addition, Deletion int
+ Type DiffFileType
+ IsCreated bool
+ IsDeleted bool
+ IsBin bool
+ IsRenamed bool
+ IsSubmodule bool
+ Sections []*DiffSection
+ IsIncomplete bool
+}
+
+func (diffFile *DiffFile) GetType() int {
+ return int(diffFile.Type)
+}
+
+func (diffFile *DiffFile) NumSections() int {
+ return len(diffFile.Sections)
+}
+
+// Diff contains all information of a specific diff output.
+type Diff struct {
+ TotalAddition, TotalDeletion int
+ Files []*DiffFile
+ IsIncomplete bool
+}
+
+func (diff *Diff) NumFiles() int {
+ return len(diff.Files)
+}
+
+const _DIFF_HEAD = "diff --git "
+
+// ParsePatch takes a reader and parses everything it receives in diff format.
+func ParsePatch(done chan<- error, maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) *Diff {
+ var (
+ diff = &Diff{Files: make([]*DiffFile, 0)}
+
+ curFile *DiffFile
+ curSection = &DiffSection{
+ Lines: make([]*DiffLine, 0, 10),
+ }
+
+ leftLine, rightLine int
+ lineCount int
+ curFileLinesCount int
+ )
+ input := bufio.NewReader(reader)
+ isEOF := false
+ for !isEOF {
+ // TODO: would input.ReadBytes be more memory-efficient?
+ line, err := input.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ isEOF = true
+ } else {
+ done <- fmt.Errorf("ReadString: %v", err)
+ return nil
+ }
+ }
+
+ if len(line) > 0 && line[len(line)-1] == '\n' {
+ // Remove line break.
+ line = line[:len(line)-1]
+ }
+
+ if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 {
+ continue
+ }
+
+ curFileLinesCount++
+ lineCount++
+
+ // Diff data too large, we only show the first about maxlines lines
+ if curFileLinesCount >= maxLines || len(line) >= maxLineCharacteres {
+ curFile.IsIncomplete = true
+ }
+
+ switch {
+ case line[0] == ' ':
+ diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine}
+ leftLine++
+ rightLine++
+ curSection.Lines = append(curSection.Lines, diffLine)
+ continue
+ case line[0] == '@':
+ curSection = &DiffSection{}
+ curFile.Sections = append(curFile.Sections, curSection)
+ ss := strings.Split(line, "@@")
+ diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line}
+ curSection.Lines = append(curSection.Lines, diffLine)
+
+ // Parse line number.
+ ranges := strings.Split(ss[1][1:], " ")
+ leftLine, _ = strconv.Atoi(strings.Split(ranges[0], ",")[0][1:])
+ if len(ranges) > 1 {
+ rightLine, _ = strconv.Atoi(strings.Split(ranges[1], ",")[0])
+ } else {
+ rightLine = leftLine
+ }
+ continue
+ case line[0] == '+':
+ curFile.Addition++
+ diff.TotalAddition++
+ diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine}
+ rightLine++
+ curSection.Lines = append(curSection.Lines, diffLine)
+ continue
+ case line[0] == '-':
+ curFile.Deletion++
+ diff.TotalDeletion++
+ diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine}
+ if leftLine > 0 {
+ leftLine++
+ }
+ curSection.Lines = append(curSection.Lines, diffLine)
+ case strings.HasPrefix(line, "Binary"):
+ curFile.IsBin = true
+ continue
+ }
+
+ // Get new file.
+ if strings.HasPrefix(line, _DIFF_HEAD) {
+ middle := -1
+
+ // Note: In case file name is surrounded by double quotes (it happens only in git-shell).
+ // e.g. diff --git "a/xxx" "b/xxx"
+ hasQuote := line[len(_DIFF_HEAD)] == '"'
+ if hasQuote {
+ middle = strings.Index(line, ` "b/`)
+ } else {
+ middle = strings.Index(line, " b/")
+ }
+
+ beg := len(_DIFF_HEAD)
+ a := line[beg+2 : middle]
+ b := line[middle+3:]
+ if hasQuote {
+ a = string(UnescapeChars([]byte(a[1 : len(a)-1])))
+ b = string(UnescapeChars([]byte(b[1 : len(b)-1])))
+ }
+
+ curFile = &DiffFile{
+ Name: a,
+ Type: DIFF_FILE_CHANGE,
+ Sections: make([]*DiffSection, 0, 10),
+ }
+ diff.Files = append(diff.Files, curFile)
+ if len(diff.Files) >= maxFiles {
+ diff.IsIncomplete = true
+ io.Copy(ioutil.Discard, reader)
+ break
+ }
+ curFileLinesCount = 0
+
+ // Check file diff type and submodule.
+ CHECK_TYPE:
+ for {
+ line, err := input.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ isEOF = true
+ } else {
+ done <- fmt.Errorf("ReadString: %v", err)
+ return nil
+ }
+ }
+
+ switch {
+ case strings.HasPrefix(line, "new file"):
+ curFile.Type = DIFF_FILE_ADD
+ curFile.IsCreated = true
+ curFile.IsSubmodule = strings.HasSuffix(line, " 160000\n")
+ case strings.HasPrefix(line, "deleted"):
+ curFile.Type = DIFF_FILE_DEL
+ curFile.IsDeleted = true
+ curFile.IsSubmodule = strings.HasSuffix(line, " 160000\n")
+ case strings.HasPrefix(line, "index"):
+ if curFile.IsDeleted {
+ curFile.Index = line[6:46]
+ } else if len(line) >= 88 {
+ curFile.Index = line[49:88]
+ } else {
+ curFile.Index = curFile.Name
+ }
+ break CHECK_TYPE
+ case strings.HasPrefix(line, "similarity index 100%"):
+ curFile.Type = DIFF_FILE_RENAME
+ curFile.IsRenamed = true
+ curFile.OldName = curFile.Name
+ curFile.Name = b
+ curFile.Index = b
+ break CHECK_TYPE
+ }
+ }
+ }
+ }
+
+ done <- nil
+ return diff
+}
+
+// GetDiffRange returns a parsed diff object between given commits.
+func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
+ repo, err := OpenRepository(repoPath)
+ if err != nil {
+ return nil, err
+ }
+
+ commit, err := repo.GetCommit(afterCommitID)
+ if err != nil {
+ return nil, err
+ }
+
+ cmd := NewCommand()
+ if len(beforeCommitID) == 0 {
+ // First commit of repository
+ if commit.ParentCount() == 0 {
+ cmd.AddArguments("show", "--full-index", afterCommitID)
+ } else {
+ c, _ := commit.Parent(0)
+ cmd.AddArguments("diff", "--full-index", "-M", c.ID.String(), afterCommitID)
+ }
+ } else {
+ cmd.AddArguments("diff", "--full-index", "-M", beforeCommitID, afterCommitID)
+ }
+
+ stdout, w := io.Pipe()
+ done := make(chan error)
+ var diff *Diff
+ go func() {
+ diff = ParsePatch(done, maxLines, maxLineCharacteres, maxFiles, stdout)
+ }()
+
+ stderr := new(bytes.Buffer)
+ err = cmd.RunInDirTimeoutPipeline(2*time.Minute, repoPath, w, stderr)
+ w.Close() // Close writer to exit parsing goroutine
+ if err != nil {
+ return nil, concatenateError(err, stderr.String())
+ }
+
+ return diff, <-done
+}
+
+// RawDiffType represents the type of raw diff format.
+type RawDiffType string
+
+const (
+ RAW_DIFF_NORMAL RawDiffType = "diff"
+ RAW_DIFF_PATCH RawDiffType = "patch"
+)
+
+// GetRawDiff dumps diff results of repository in given commit ID to io.Writer.
+func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Writer) error {
+ repo, err := OpenRepository(repoPath)
+ if err != nil {
+ return fmt.Errorf("OpenRepository: %v", err)
+ }
+
+ commit, err := repo.GetCommit(commitID)
+ if err != nil {
+ return err
+ }
+
+ cmd := NewCommand()
+ switch diffType {
+ case RAW_DIFF_NORMAL:
+ if commit.ParentCount() == 0 {
+ cmd.AddArguments("show", commitID)
+ } else {
+ c, _ := commit.Parent(0)
+ cmd.AddArguments("diff", "-M", c.ID.String(), commitID)
+ }
+ case RAW_DIFF_PATCH:
+ if commit.ParentCount() == 0 {
+ cmd.AddArguments("format-patch", "--no-signature", "--stdout", "--root", commitID)
+ } else {
+ c, _ := commit.Parent(0)
+ query := fmt.Sprintf("%s...%s", commitID, c.ID.String())
+ cmd.AddArguments("format-patch", "--no-signature", "--stdout", query)
+ }
+ default:
+ return fmt.Errorf("invalid diffType: %s", diffType)
+ }
+
+ stderr := new(bytes.Buffer)
+ if err = cmd.RunInDirPipeline(repoPath, writer, stderr); err != nil {
+ return concatenateError(err, stderr.String())
+ }
+ return nil
+}
+
+// GetDiffCommit returns a parsed diff object of given commit.
+func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
+ return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacteres, maxFiles)
+}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 6e778e6a..762d1f70 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -159,10 +159,10 @@
"revisionTime": "2016-08-10T03:50:02Z"
},
{
- "checksumSHA1": "WVDLV+YcA77fg1kgddSinycf3Do=",
+ "checksumSHA1": "iZ3qMzzA24U3eqGifUZa6kFuCqk=",
"path": "github.com/gogits/git-module",
- "revision": "f4026b57acf35d799d5dec95066f3a10c572604e",
- "revisionTime": "2017-04-03T19:07:43Z"
+ "revision": "5dba4f883034198eabac620b73aabf5488fcd821",
+ "revisionTime": "2017-04-04T05:34:13Z"
},
{
"checksumSHA1": "D2kVXl0QpIw6t3891Sl7IM9wL+w=",