mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	* Inital routes to git refs api * Git refs API implementation * Update swagger * Fix copyright * Make swagger happy add basic test * Fix test * Fix test again :)
		
			
				
	
	
		
			184 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package object
 | 
						|
 | 
						|
import (
 | 
						|
	"io"
 | 
						|
 | 
						|
	"gopkg.in/src-d/go-git.v4/plumbing"
 | 
						|
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
 | 
						|
)
 | 
						|
 | 
						|
type commitPreIterator struct {
 | 
						|
	seenExternal map[plumbing.Hash]bool
 | 
						|
	seen         map[plumbing.Hash]bool
 | 
						|
	stack        []CommitIter
 | 
						|
	start        *Commit
 | 
						|
}
 | 
						|
 | 
						|
// NewCommitPreorderIter returns a CommitIter that walks the commit history,
 | 
						|
// starting at the given commit and visiting its parents in pre-order.
 | 
						|
// The given callback will be called for each visited commit. Each commit will
 | 
						|
// be visited only once. If the callback returns an error, walking will stop
 | 
						|
// and will return the error. Other errors might be returned if the history
 | 
						|
// cannot be traversed (e.g. missing objects). Ignore allows to skip some
 | 
						|
// commits from being iterated.
 | 
						|
func NewCommitPreorderIter(
 | 
						|
	c *Commit,
 | 
						|
	seenExternal map[plumbing.Hash]bool,
 | 
						|
	ignore []plumbing.Hash,
 | 
						|
) CommitIter {
 | 
						|
	seen := make(map[plumbing.Hash]bool)
 | 
						|
	for _, h := range ignore {
 | 
						|
		seen[h] = true
 | 
						|
	}
 | 
						|
 | 
						|
	return &commitPreIterator{
 | 
						|
		seenExternal: seenExternal,
 | 
						|
		seen:         seen,
 | 
						|
		stack:        make([]CommitIter, 0),
 | 
						|
		start:        c,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (w *commitPreIterator) Next() (*Commit, error) {
 | 
						|
	var c *Commit
 | 
						|
	for {
 | 
						|
		if w.start != nil {
 | 
						|
			c = w.start
 | 
						|
			w.start = nil
 | 
						|
		} else {
 | 
						|
			current := len(w.stack) - 1
 | 
						|
			if current < 0 {
 | 
						|
				return nil, io.EOF
 | 
						|
			}
 | 
						|
 | 
						|
			var err error
 | 
						|
			c, err = w.stack[current].Next()
 | 
						|
			if err == io.EOF {
 | 
						|
				w.stack = w.stack[:current]
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			if err != nil {
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if w.seen[c.Hash] || w.seenExternal[c.Hash] {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		w.seen[c.Hash] = true
 | 
						|
 | 
						|
		if c.NumParents() > 0 {
 | 
						|
			w.stack = append(w.stack, filteredParentIter(c, w.seen))
 | 
						|
		}
 | 
						|
 | 
						|
		return c, nil
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func filteredParentIter(c *Commit, seen map[plumbing.Hash]bool) CommitIter {
 | 
						|
	var hashes []plumbing.Hash
 | 
						|
	for _, h := range c.ParentHashes {
 | 
						|
		if !seen[h] {
 | 
						|
			hashes = append(hashes, h)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return NewCommitIter(c.s,
 | 
						|
		storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, hashes),
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
func (w *commitPreIterator) ForEach(cb func(*Commit) error) error {
 | 
						|
	for {
 | 
						|
		c, err := w.Next()
 | 
						|
		if err == io.EOF {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		err = cb(c)
 | 
						|
		if err == storer.ErrStop {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (w *commitPreIterator) Close() {}
 | 
						|
 | 
						|
type commitPostIterator struct {
 | 
						|
	stack []*Commit
 | 
						|
	seen  map[plumbing.Hash]bool
 | 
						|
}
 | 
						|
 | 
						|
// NewCommitPostorderIter returns a CommitIter that walks the commit
 | 
						|
// history like WalkCommitHistory but in post-order. This means that after
 | 
						|
// walking a merge commit, the merged commit will be walked before the base
 | 
						|
// it was merged on. This can be useful if you wish to see the history in
 | 
						|
// chronological order. Ignore allows to skip some commits from being iterated.
 | 
						|
func NewCommitPostorderIter(c *Commit, ignore []plumbing.Hash) CommitIter {
 | 
						|
	seen := make(map[plumbing.Hash]bool)
 | 
						|
	for _, h := range ignore {
 | 
						|
		seen[h] = true
 | 
						|
	}
 | 
						|
 | 
						|
	return &commitPostIterator{
 | 
						|
		stack: []*Commit{c},
 | 
						|
		seen:  seen,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (w *commitPostIterator) Next() (*Commit, error) {
 | 
						|
	for {
 | 
						|
		if len(w.stack) == 0 {
 | 
						|
			return nil, io.EOF
 | 
						|
		}
 | 
						|
 | 
						|
		c := w.stack[len(w.stack)-1]
 | 
						|
		w.stack = w.stack[:len(w.stack)-1]
 | 
						|
 | 
						|
		if w.seen[c.Hash] {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		w.seen[c.Hash] = true
 | 
						|
 | 
						|
		return c, c.Parents().ForEach(func(p *Commit) error {
 | 
						|
			w.stack = append(w.stack, p)
 | 
						|
			return nil
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (w *commitPostIterator) ForEach(cb func(*Commit) error) error {
 | 
						|
	for {
 | 
						|
		c, err := w.Next()
 | 
						|
		if err == io.EOF {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		err = cb(c)
 | 
						|
		if err == storer.ErrStop {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (w *commitPostIterator) Close() {}
 |