mirror of
https://github.com/go-gitea/gitea.git
synced 2024-10-18 06:33:44 -04:00
116 lines
2.8 KiB
Go
116 lines
2.8 KiB
Go
|
package object
|
||
|
|
||
|
import (
|
||
|
"gopkg.in/src-d/go-git.v4/plumbing/storer"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
type commitFileIter struct {
|
||
|
fileName string
|
||
|
sourceIter CommitIter
|
||
|
currentCommit *Commit
|
||
|
}
|
||
|
|
||
|
// NewCommitFileIterFromIter returns a commit iterator which performs diffTree between
|
||
|
// successive trees returned from the commit iterator from the argument. The purpose of this is
|
||
|
// to find the commits that explain how the files that match the path came to be.
|
||
|
func NewCommitFileIterFromIter(fileName string, commitIter CommitIter) CommitIter {
|
||
|
iterator := new(commitFileIter)
|
||
|
iterator.sourceIter = commitIter
|
||
|
iterator.fileName = fileName
|
||
|
return iterator
|
||
|
}
|
||
|
|
||
|
func (c *commitFileIter) Next() (*Commit, error) {
|
||
|
if c.currentCommit == nil {
|
||
|
var err error
|
||
|
c.currentCommit, err = c.sourceIter.Next()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
commit, commitErr := c.getNextFileCommit()
|
||
|
|
||
|
// Setting current-commit to nil to prevent unwanted states when errors are raised
|
||
|
if commitErr != nil {
|
||
|
c.currentCommit = nil
|
||
|
}
|
||
|
return commit, commitErr
|
||
|
}
|
||
|
|
||
|
func (c *commitFileIter) getNextFileCommit() (*Commit, error) {
|
||
|
for {
|
||
|
// Parent-commit can be nil if the current-commit is the initial commit
|
||
|
parentCommit, parentCommitErr := c.sourceIter.Next()
|
||
|
if parentCommitErr != nil {
|
||
|
// If the parent-commit is beyond the initial commit, keep it nil
|
||
|
if parentCommitErr != io.EOF {
|
||
|
return nil, parentCommitErr
|
||
|
}
|
||
|
parentCommit = nil
|
||
|
}
|
||
|
|
||
|
// Fetch the trees of the current and parent commits
|
||
|
currentTree, currTreeErr := c.currentCommit.Tree()
|
||
|
if currTreeErr != nil {
|
||
|
return nil, currTreeErr
|
||
|
}
|
||
|
|
||
|
var parentTree *Tree
|
||
|
if parentCommit != nil {
|
||
|
var parentTreeErr error
|
||
|
parentTree, parentTreeErr = parentCommit.Tree()
|
||
|
if parentTreeErr != nil {
|
||
|
return nil, parentTreeErr
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Find diff between current and parent trees
|
||
|
changes, diffErr := DiffTree(currentTree, parentTree)
|
||
|
if diffErr != nil {
|
||
|
return nil, diffErr
|
||
|
}
|
||
|
|
||
|
foundChangeForFile := false
|
||
|
for _, change := range changes {
|
||
|
if change.name() == c.fileName {
|
||
|
foundChangeForFile = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Storing the current-commit in-case a change is found, and
|
||
|
// Updating the current-commit for the next-iteration
|
||
|
prevCommit := c.currentCommit
|
||
|
c.currentCommit = parentCommit
|
||
|
|
||
|
if foundChangeForFile == true {
|
||
|
return prevCommit, nil
|
||
|
}
|
||
|
|
||
|
// If not matches found and if parent-commit is beyond the initial commit, then return with EOF
|
||
|
if parentCommit == nil {
|
||
|
return nil, io.EOF
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *commitFileIter) ForEach(cb func(*Commit) error) error {
|
||
|
for {
|
||
|
commit, nextErr := c.Next()
|
||
|
if nextErr != nil {
|
||
|
return nextErr
|
||
|
}
|
||
|
err := cb(commit)
|
||
|
if err == storer.ErrStop {
|
||
|
return nil
|
||
|
} else if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *commitFileIter) Close() {
|
||
|
c.sourceIter.Close()
|
||
|
}
|