| @@ -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 | |||
| } | |||
| }*/ | |||