Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
3.1 kB · 160 lines
Go
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161package git
import ( "context" "errors" "fmt" "path" "time"
"github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/object" "tangled.org/core/types")
func (g *GitRepo) FileTree(ctx context.Context, path string) ([]types.NiceTree, error) { c, err := g.r.CommitObject(g.h) if err != nil { return nil, fmt.Errorf("commit object: %w", err) }
files := []types.NiceTree{} tree, err := c.Tree() if err != nil { return nil, fmt.Errorf("file tree: %w", err) }
if path == "" { files = g.makeNiceTree(ctx, tree, "") } else { o, err := tree.FindEntry(path) if err != nil { return nil, err }
if !o.Mode.IsFile() { subtree, err := tree.Tree(path) if err != nil { return nil, err }
files = g.makeNiceTree(ctx, subtree, path) } }
return files, nil}
func (g *GitRepo) makeNiceTree(ctx context.Context, subtree *object.Tree, parent string) []types.NiceTree { nts := []types.NiceTree{}
entries := make([]string, len(subtree.Entries)) for _, e := range subtree.Entries { entries = append(entries, e.Name) }
lastCommitDir := lastCommitDir{ dir: parent, entries: entries, }
times, err := g.lastCommitDirIn(ctx, lastCommitDir, 2*time.Second) if err != nil { return nts }
for _, e := range subtree.Entries { sz, _ := subtree.Size(e.Name) fpath := path.Join(parent, e.Name)
var lastCommit *types.LastCommitInfo if t, ok := times[fpath]; ok { lastCommit = &types.LastCommitInfo{ Hash: t.hash, Message: t.message, When: t.when, } }
nts = append(nts, types.NiceTree{ Name: e.Name, Mode: e.Mode.String(), Size: sz, LastCommit: lastCommit, })
}
return nts}
var ( TerminateWalk error = errors.New("terminate walk"))
type callback = func(node object.TreeEntry, parent *object.Tree, fullPath string) error
func (g *GitRepo) Walk( ctx context.Context, root string, cb callback,) error { c, err := g.r.CommitObject(g.h) if err != nil { return fmt.Errorf("commit object: %w", err) }
tree, err := c.Tree() if err != nil { return fmt.Errorf("file tree: %w", err) }
subtree := tree if root != "" { subtree, err = tree.Tree(root) if err != nil { return fmt.Errorf("sub tree: %w", err) } }
return g.walkHelper(ctx, root, subtree, cb)}
func (g *GitRepo) walkHelper( ctx context.Context, root string, currentTree *object.Tree, cb callback,) error { for _, e := range currentTree.Entries { // check if context hits deadline before processing select { case <-ctx.Done(): return ctx.Err() default: }
if e.Mode.IsFile() { if err := cb(e, currentTree, root); errors.Is(err, TerminateWalk) { return err } }
// e is a directory if e.Mode == filemode.Dir { subtree, err := currentTree.Tree(e.Name) if err != nil { return fmt.Errorf("sub tree %s: %w", e.Name, err) }
fullPath := path.Join(root, e.Name)
err = g.walkHelper(ctx, fullPath, subtree, cb) if err != nil { return err } } }
return nil}