瀏覽代碼

improved diff

Lunny Xiao 11 年之前
父節點
當前提交
74b3c953de
共有 1 個文件被更改,包括 138 次插入6 次删除
  1. 138 6
      models/git.go

+ 138 - 6
models/git.go

@@ -9,8 +9,10 @@ import (
 	"fmt"
 	"path"
 	"strings"
-
-	"github.com/Unknwon/com"
+	"io"
+	"bufio"
+	"os"
+	"os/exec"
 
 	"github.com/gogits/git"
 )
@@ -226,20 +228,150 @@ func GetCommits(userName, reposName, branchname string) (*list.List, error) {
 	return r.AllCommits()
 }
 
+const (
+	PlainLine = iota + 1
+	AddLine
+	DelLine
+	SectionLine
+)
+
+const (
+	AddFile = iota + 1
+	ChangeFile
+	DelFile
+)
+
+type DiffLine struct {
+	LeftIdx int
+	RightIdx int
+	Type int
+	Content string
+}
+
+type DiffSection struct {
+	Name string
+	Lines []*DiffLine
+}
+
 type DiffFile struct {
 	Name               string
 	Addition, Deletion int
-	Type               string
-	Content            []string
+	Type               int
+	Sections            []*DiffSection
 }
 
 type Diff struct {
-	NumFiles                     int // Number of file has been changed.
 	TotalAddition, TotalDeletion int
 	Files                        []*DiffFile
 }
 
+func (diff *Diff) NumFiles() int {
+	return len(diff.Files)
+}
+
+const diffHead = "diff --git "
+
+func ParsePatch(reader io.Reader) (*Diff, error) {
+	scanner := bufio.NewScanner(reader)
+	var totalAdd, totalDel int
+	var curFile *DiffFile
+	var curSection * DiffSection
+	//var leftLine, rightLine int
+	diff := &Diff{Files:make([]*DiffFile, 0)}
+	var i int
+	for scanner.Scan() {
+		line := scanner.Text()
+		fmt.Println(i, line)
+		i = i + 1
+		if line == "" {
+			continue
+		}
+		if line[0] == ' ' {
+			diffLine := &DiffLine{Type: PlainLine, Content:line}
+			curSection.Lines = append(curSection.Lines, diffLine)
+			continue
+		} else if line[0] == '@' {
+			ss := strings.Split(line, "@@")
+			diffLine := &DiffLine{Type: SectionLine, Content:"@@ "+ss[len(ss)-2]}
+			curSection.Lines = append(curSection.Lines, diffLine)
+
+
+
+			diffLine = &DiffLine{Type: PlainLine, Content:ss[len(ss)-1]}
+			curSection.Lines = append(curSection.Lines, diffLine)
+			continue
+		} else if line[0] == '+' {
+			diffLine := &DiffLine{Type: AddLine, Content:line}
+			curSection.Lines = append(curSection.Lines, diffLine)
+			continue
+		} else if line[0] == '-' {
+			diffLine := &DiffLine{Type: DelLine, Content:line}
+			curSection.Lines = append(curSection.Lines, diffLine)
+			continue
+		}
+
+		if strings.HasPrefix(line, diffHead) {
+			if curFile != nil {
+				curFile.Addition, totalAdd = totalAdd, 0
+				curFile.Deletion, totalDel = totalDel, 0
+				curFile = nil
+			}
+			fs := strings.Split(line[len(diffHead):], " ")
+			a := fs[0]
+			
+			curFile = &DiffFile{
+				Name:a[strings.Index(a, "/")+1:], 
+				Type: ChangeFile,
+				Sections:make([]*DiffSection, 0),
+			}
+			diff.Files = append(diff.Files, curFile)
+			scanner.Scan()
+			scanner.Scan()
+			if scanner.Text() == "--- /dev/null" {
+				curFile.Type = AddFile
+			}
+			scanner.Scan()
+		}
+	}
+
+	return diff, nil
+}
+
 func GetDiff(repoPath, commitid string) (*Diff, error) {
+	repo, err := git.OpenRepository(repoPath)
+	if err != nil {
+		return nil, err
+	}
+
+	commit, err := repo.GetCommit("", commitid)
+	if err != nil {
+		return nil, err
+	}
+
+	if commit.ParentCount() == 0 {
+		return nil, err
+	}
+
+	rd, wr := io.Pipe()
+	go func() {
+		cmd := exec.Command("git", "diff", commitid, commit.Parent(0).Oid.String())
+		cmd.Dir = repoPath
+		cmd.Stdout = wr
+		cmd.Stdin = os.Stdin
+		cmd.Stderr = os.Stderr
+		cmd.Run()
+		//if err != nil {
+		//	return nil, err
+		//}
+		wr.Close()
+	}()
+
+	defer rd.Close()
+
+	return ParsePatch(rd)
+}
+
+/*func GetDiff(repoPath, commitid string) (*Diff, error) {
 	stdout, _, err := com.ExecCmdDir(repoPath, "git", "show", commitid)
 	if err != nil {
 		return nil, err
@@ -271,4 +403,4 @@ func GetDiff(repoPath, commitid string) (*Diff, error) {
 		diff.Files = append(diff.Files, file)
 	}
 	return diff, nil
-}
+}*/