1package git23import (4 "context"5 "strings"6 "sync"7)89// Tree represents a flat directory listing in Git.10type Tree struct {11 id Oid12 parent *Tree1314 repo *Repository1516 entries Entries17 entriesMu sync.Mutex18 entriesSet bool19}2021// Subtree returns a subtree by given subpath of the tree.22func (t *Tree) Subtree(ctx context.Context, subpath string, opts ...LsTreeOptions) (*Tree, error) {23 if len(subpath) == 0 {24 return t, nil25 }2627 paths := strings.Split(subpath, "/")28 var (29 err error30 g = t31 p = t32 e *TreeEntry33 )34 for _, name := range paths {35 e, err = p.TreeEntry(ctx, name, opts...)36 if err != nil {37 return nil, err38 }3940 g = &Tree{41 id: e.id,42 parent: p,43 repo: t.repo,44 }45 p = g46 }47 return g, nil48}4950// Entries returns all entries of the tree. Successful results are cached;51// failed attempts are not cached, allowing retries with a fresh context.52func (t *Tree) Entries(ctx context.Context, opts ...LsTreeOptions) (Entries, error) {53 t.entriesMu.Lock()54 defer t.entriesMu.Unlock()5556 if t.entriesSet {57 return t.entries, nil58 }5960 tt, err := t.repo.LsTree(ctx, t.id.String(), opts...)61 if err != nil {62 return nil, err63 }64 t.entries = tt.entries65 t.entriesSet = true66 return t.entries, nil67}