func (iter *TreeIter) ForEach(cb func(*Tree) error) error {
	return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
		if obj.Type() != plumbing.TreeObject {
			return nil
		}
		t, err := DecodeTree(iter.s, obj)
		if err != nil {
			return err
		}
		return cb(t)
	})
}
ForEach call the cb function for each tree contained on this iter until
an error happens or the end of the iter is reached. If ErrStop is sent
the iteration is stop but no error is returned. The iterator is closed.
package object
import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"path"
	"strings"
	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
	"gopkg.in/src-d/go-git.v4/utils/ioutil"
)
const (
	maxTreeDepth      = 1024
	startingStackSize = 8
)
var (
	ErrMaxTreeDepth      = errors.New("maximum tree depth exceeded")
	ErrFileNotFound      = errors.New("file not found")
	ErrDirectoryNotFound = errors.New("directory not found")
)
type Tree struct {
	Entries []TreeEntry
	Hash    plumbing.Hash
	s storer.EncodedObjectStorer
	m map[string]*TreeEntry
}
func GetTree(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tree, error) {
	o, err := s.EncodedObject(plumbing.TreeObject, h)
	if err != nil {
		return nil, err
	}
	return DecodeTree(s, o)
}
func DecodeTree(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tree, error) {
	t := &Tree{s: s}
	if err := t.Decode(o); err != nil {
		return nil, err
	}
	return t, nil
}
type TreeEntry struct {
	Name string
	Mode filemode.FileMode
	Hash plumbing.Hash
}
func (t *Tree) File(path string) (*File, error) {
	e, err := t.FindEntry(path)
	if err != nil {
		return nil, ErrFileNotFound
	}
	blob, err := GetBlob(t.s, e.Hash)
	if err != nil {
		if err == plumbing.ErrObjectNotFound {
			return nil, ErrFileNotFound
		}
		return nil, err
	}
	return NewFile(path, e.Mode, blob), nil
}
func (t *Tree) Tree(path string) (*Tree, error) {
	e, err := t.FindEntry(path)
	if err != nil {
		return nil, ErrDirectoryNotFound
	}
	tree, err := GetTree(t.s, e.Hash)
	if err == plumbing.ErrObjectNotFound {
		return nil, ErrDirectoryNotFound
	}
	return tree, err
}
func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error) {
	blob, err := GetBlob(t.s, e.Hash)
	if err != nil {
		return nil, err
	}
	return NewFile(e.Name, e.Mode, blob), nil
}
func (t *Tree) FindEntry(path string) (*TreeEntry, error) {
	pathParts := strings.Split(path, "/")
	var tree *Tree
	var err error
	for tree = t; len(pathParts) > 1; pathParts = pathParts[1:] {
		if tree, err = tree.dir(pathParts[0]); err != nil {
			return nil, err
		}
	}
	return tree.entry(pathParts[0])
}
func (t *Tree) dir(baseName string) (*Tree, error) {
	entry, err := t.entry(baseName)
	if err != nil {
		return nil, ErrDirectoryNotFound
	}
	obj, err := t.s.EncodedObject(plumbing.TreeObject, entry.Hash)
	if err != nil {
		return nil, err
	}
	tree := &Tree{s: t.s}
	err = tree.Decode(obj)
	return tree, err
}
var errEntryNotFound = errors.New("entry not found")
func (t *Tree) entry(baseName string) (*TreeEntry, error) {
	if t.m == nil {
		t.buildMap()
	}
	entry, ok := t.m[baseName]
	if !ok {
		return nil, errEntryNotFound
	}
	return entry, nil
}
func (t *Tree) Files() *FileIter {
	return NewFileIter(t.s, t)
}
func (t *Tree) ID() plumbing.Hash {
	return t.Hash
}
func (t *Tree) Type() plumbing.ObjectType {
	return plumbing.TreeObject
}
func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
	if o.Type() != plumbing.TreeObject {
		return ErrUnsupportedObject
	}
	t.Hash = o.Hash()
	if o.Size() == 0 {
		return nil
	}
	t.Entries = nil
	t.m = nil
	reader, err := o.Reader()
	if err != nil {
		return err
	}
	defer ioutil.CheckClose(reader, &err)
	r := bufio.NewReader(reader)
	for {
		str, err := r.ReadString(' ')
		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		str = str[:len(str)-1]  
		mode, err := filemode.New(str)
		if err != nil {
			return err
		}
		name, err := r.ReadString(0)
		if err != nil && err != io.EOF {
			return err
		}
		var hash plumbing.Hash
		if _, err = io.ReadFull(r, hash[:]); err != nil {
			return err
		}
		baseName := name[:len(name)-1]
		t.Entries = append(t.Entries, TreeEntry{
			Hash: hash,
			Mode: mode,
			Name: baseName,
		})
	}
	return nil
}
func (t *Tree) Encode(o plumbing.EncodedObject) error {
	o.SetType(plumbing.TreeObject)
	w, err := o.Writer()
	if err != nil {
		return err
	}
	defer ioutil.CheckClose(w, &err)
	for _, entry := range t.Entries {
		if _, err := fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil {
			return err
		}
		if _, err = w.Write([]byte{0x00}); err != nil {
			return err
		}
		if _, err = w.Write([]byte(entry.Hash[:])); err != nil {
			return err
		}
	}
	return err
}
func (t *Tree) buildMap() {
	t.m = make(map[string]*TreeEntry)
	for i := 0; i < len(t.Entries); i++ {
		t.m[t.Entries[i].Name] = &t.Entries[i]
	}
}
func (from *Tree) Diff(to *Tree) (Changes, error) {
	return DiffTree(from, to)
}
func (from *Tree) Patch(to *Tree) (*Patch, error) {
	changes, err := DiffTree(from, to)
	if err != nil {
		return nil, err
	}
	return changes.Patch()
}
type treeEntryIter struct {
	t   *Tree
	pos int
}
func (iter *treeEntryIter) Next() (TreeEntry, error) {
	if iter.pos >= len(iter.t.Entries) {
		return TreeEntry{}, io.EOF
	}
	iter.pos++
	return iter.t.Entries[iter.pos-1], nil
}
type TreeWalker struct {
	stack     []*treeEntryIter
	base      string
	recursive bool
	seen      map[plumbing.Hash]bool
	s storer.EncodedObjectStorer
	t *Tree
}
func NewTreeWalker(t *Tree, recursive bool, seen map[plumbing.Hash]bool) *TreeWalker {
	stack := make([]*treeEntryIter, 0, startingStackSize)
	stack = append(stack, &treeEntryIter{t, 0})
	return &TreeWalker{
		stack:     stack,
		recursive: recursive,
		seen:      seen,
		s: t.s,
		t: t,
	}
}
func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
	var obj Object
	for {
		current := len(w.stack) - 1
		if current < 0 {
			err = io.EOF
			return
		}
		if current > maxTreeDepth {
			err = ErrMaxTreeDepth
			return
		}
		entry, err = w.stack[current].Next()
		if err == io.EOF {
			w.stack = w.stack[:current]
			w.base, _ = path.Split(w.base)
			w.base = path.Clean(w.base)  
			continue
		}
		if err != nil {
			return
		}
		if w.seen[entry.Hash] {
			continue
		}
		if entry.Mode == filemode.Dir {
			obj, err = GetTree(w.s, entry.Hash)
		}
		name = path.Join(w.base, entry.Name)
		if err != nil {
			err = io.EOF
			return
		}
		break
	}
	if !w.recursive {
		return
	}
	if t, ok := obj.(*Tree); ok {
		w.stack = append(w.stack, &treeEntryIter{t, 0})
		w.base = path.Join(w.base, entry.Name)
	}
	return
}
func (w *TreeWalker) Tree() *Tree {
	current := len(w.stack) - 1
	if w.stack[current].pos == 0 {
		current--
	}
	if current < 0 {
		return nil
	}
	return w.stack[current].t
}
func (w *TreeWalker) Close() {
	w.stack = nil
}
type TreeIter struct {
	storer.EncodedObjectIter
	s storer.EncodedObjectStorer
}
func NewTreeIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TreeIter {
	return &TreeIter{iter, s}
}
func (iter *TreeIter) Next() (*Tree, error) {
	for {
		obj, err := iter.EncodedObjectIter.Next()
		if err != nil {
			return nil, err
		}
		if obj.Type() != plumbing.TreeObject {
			continue
		}
		return DecodeTree(iter.s, obj)
	}
}