// Copyright 2015 The Gogs Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package git import ( "io" "strings" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" ) // Tree represents a flat directory listing. type Tree struct { ID SHA1 ResolvedID SHA1 repo *Repository gogitTree *object.Tree // parent tree ptree *Tree } // NewTree create a new tree according the repository and tree id func NewTree(repo *Repository, id SHA1) *Tree { return &Tree{ ID: id, repo: repo, } } // SubTree get a sub tree by the sub dir path func (t *Tree) SubTree(rpath string) (*Tree, error) { if len(rpath) == 0 { return t, nil } paths := strings.Split(rpath, "/") var ( err error g = t p = t te *TreeEntry ) for _, name := range paths { te, err = p.GetTreeEntryByPath(name) if err != nil { return nil, err } g, err = t.repo.getTree(te.ID) if err != nil { return nil, err } g.ptree = p p = g } return g, nil } func (t *Tree) loadTreeObject() error { gogitTree, err := t.repo.gogitRepo.TreeObject(t.ID) if err != nil { return err } t.gogitTree = gogitTree return nil } // ListEntries returns all entries of current tree. func (t *Tree) ListEntries() (Entries, error) { if t.gogitTree == nil { err := t.loadTreeObject() if err != nil { return nil, err } } entries := make([]*TreeEntry, len(t.gogitTree.Entries)) for i, entry := range t.gogitTree.Entries { entries[i] = &TreeEntry{ ID: entry.Hash, gogitTreeEntry: &t.gogitTree.Entries[i], ptree: t, } } return entries, nil } // ListEntriesRecursive returns all entries of current tree recursively including all subtrees func (t *Tree) ListEntriesRecursive() (Entries, error) { if t.gogitTree == nil { err := t.loadTreeObject() if err != nil { return nil, err } } var entries []*TreeEntry seen := map[plumbing.Hash]bool{} walker := object.NewTreeWalker(t.gogitTree, true, seen) for { fullName, entry, err := walker.Next() if err == io.EOF { break } if err != nil { return nil, err } if seen[entry.Hash] { continue } convertedEntry := &TreeEntry{ ID: entry.Hash, gogitTreeEntry: &entry, ptree: t, fullName: fullName, } entries = append(entries, convertedEntry) } return entries, nil }