diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2015-10-27 01:49:58 +0100 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2015-10-27 01:49:58 +0100 |
commit | 7d6c5a56c0b63705378f125523876de1a97fd1ce (patch) | |
tree | 8945a8a02d53f36a64304beaf006c4f46d61da48 /tree.go | |
parent | a2e49a59782a50a9ff116c6d17c6e3888502f2ad (diff) | |
download | go-git-7d6c5a56c0b63705378f125523876de1a97fd1ce.tar.gz |
tree and commit
Diffstat (limited to 'tree.go')
-rw-r--r-- | tree.go | 122 |
1 files changed, 122 insertions, 0 deletions
@@ -0,0 +1,122 @@ +package git + +import ( + "bufio" + "io" + "os" + "path/filepath" + "strconv" + + "gopkg.in/src-d/go-git.v2/internal" +) + +// Tree is basically like a directory - it references a bunch of other trees +// and/or blobs (i.e. files and sub-directories) +type Tree struct { + Entries []TreeEntry + Hash internal.Hash + + r *Repository +} + +// TreeEntry represents a file +type TreeEntry struct { + Name string + Mode os.FileMode + Hash internal.Hash +} + +func (t *Tree) Files() chan *File { + ch := make(chan *File, 1) + + go func() { + defer func() { close(ch) }() + t.walkEntries("", ch) + }() + + return ch +} + +func (t *Tree) walkEntries(base string, ch chan *File) { + for _, entry := range t.Entries { + obj, _ := t.r.Storage.Get(entry.Hash) + if obj.Type() == internal.TreeObject { + tree := &Tree{r: t.r} + tree.Decode(obj) + tree.walkEntries(filepath.Join(base, entry.Name), ch) + continue + } + + blob := &Blob{} + blob.Decode(obj) + + ch <- &File{Name: filepath.Join(base, entry.Name), Reader: blob.Reader()} + } +} + +// Decode transform an internal.Object into a Tree struct +func (t *Tree) Decode(o internal.Object) error { + t.Hash = o.Hash() + if o.Size() == 0 { + return nil + } + + r := bufio.NewReader(o.Reader()) + for { + mode, err := r.ReadString(' ') + if err != nil { + if err == io.EOF { + break + } + + return err + } + + fm, err := strconv.ParseInt(mode[:len(mode)-1], 8, 32) + if err != nil && err != io.EOF { + return err + } + + name, err := r.ReadString(0) + if err != nil && err != io.EOF { + return err + } + + var hash internal.Hash + _, err = r.Read(hash[:]) + if err != nil && err != io.EOF { + return err + } + + t.Entries = append(t.Entries, TreeEntry{ + Hash: hash, + Mode: os.FileMode(fm), + Name: name[:len(name)-1], + }) + } + + return nil +} + +type TreeIter struct { + iter +} + +func NewTreeIter(r *Repository) *TreeIter { + return &TreeIter{newIter(r)} +} + +func (i *TreeIter) Next() (*Tree, error) { + obj := <-i.ch + if obj == nil { + return nil, io.EOF + } + + tree := &Tree{r: i.r} + return tree, tree.Decode(obj) +} + +type File struct { + Name string + io.Reader +} |