mirror of
https://github.com/go-gitea/gitea.git
synced 2024-08-28 15:17:26 +02:00
Bumps [gopkg.in/src-d/go-git.v4](https://github.com/src-d/go-git) from 4.8.0 to 4.10.0. - [Release notes](https://github.com/src-d/go-git/releases) - [Commits](https://github.com/src-d/go-git/compare/v4.8.0...v4.10.0)
146 lines
3.5 KiB
Go
146 lines
3.5 KiB
Go
package object
|
|
|
|
import (
|
|
"io"
|
|
|
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
|
|
|
"gopkg.in/src-d/go-git.v4/plumbing/storer"
|
|
)
|
|
|
|
type commitFileIter struct {
|
|
fileName string
|
|
sourceIter CommitIter
|
|
currentCommit *Commit
|
|
checkParent bool
|
|
}
|
|
|
|
// 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.
|
|
// If checkParent is true then the function double checks if potential parent (next commit in a path)
|
|
// is one of the parents in the tree (it's used by `git log --all`).
|
|
func NewCommitFileIterFromIter(fileName string, commitIter CommitIter, checkParent bool) CommitIter {
|
|
iterator := new(commitFileIter)
|
|
iterator.sourceIter = commitIter
|
|
iterator.fileName = fileName
|
|
iterator.checkParent = checkParent
|
|
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
|
|
}
|
|
|
|
found := c.hasFileChange(changes, parentCommit)
|
|
|
|
// 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 found {
|
|
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) hasFileChange(changes Changes, parent *Commit) bool {
|
|
for _, change := range changes {
|
|
if change.name() != c.fileName {
|
|
continue
|
|
}
|
|
|
|
// filename matches, now check if source iterator contains all commits (from all refs)
|
|
if c.checkParent {
|
|
if parent != nil && isParentHash(parent.Hash, c.currentCommit) {
|
|
return true
|
|
}
|
|
continue
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func isParentHash(hash plumbing.Hash, commit *Commit) bool {
|
|
for _, h := range commit.ParentHashes {
|
|
if h == hash {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
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()
|
|
}
|