6 "github.com/git-lfs/gitobj"
9 // Tree represents the .gitattributes file at one layer of the tree in a Git
12 // Lines are the lines of the .gitattributes at this level of the tree.
14 // Children are the named child directories in the repository.
15 Children map[string]*Tree
18 // New constructs a *Tree starting at the given tree "t" and reading objects
19 // from the given ObjectDatabase. If a tree was not able to be read, an error
20 // will be propagated up accordingly.
21 func New(db *gitobj.ObjectDatabase, t *gitobj.Tree) (*Tree, error) {
22 children := make(map[string]*Tree)
23 lines, err := linesInTree(db, t)
28 for _, entry := range t.Entries {
29 if entry.Type() != gitobj.TreeObjectType {
33 // For every entry in the current tree, parse its sub-trees to
34 // see if they might contain a .gitattributes.
35 t, err := db.Tree(entry.Oid)
45 if len(at.Children) > 0 || len(at.Lines) > 0 {
46 // Only include entries that have either (1) a
47 // .gitattributes in their tree, or (2) a .gitattributes
49 children[entry.Name] = at
59 // linesInTree parses a given tree's .gitattributes and returns a slice of lines
60 // in that .gitattributes, or an error. If no .gitattributes blob was found,
62 func linesInTree(db *gitobj.ObjectDatabase, t *gitobj.Tree) ([]*Line, error) {
64 for i, e := range t.Entries {
65 if e.Name == ".gitattributes" {
75 blob, err := db.Blob(t.Entries[at].Oid)
81 return ParseLines(blob.Contents)
84 // Applied returns a slice of attributes applied to the given path, relative to
85 // the receiving tree. It traverse through sub-trees in a topological ordering,
86 // if there are relevant .gitattributes matching that path.
87 func (t *Tree) Applied(to string) []*Attr {
89 for _, line := range t.Lines {
90 if line.Pattern.Match(to) {
91 attrs = append(attrs, line.Attrs...)
95 splits := strings.SplitN(to, "/", 2)
97 car, cdr := splits[0], splits[1]
98 if child, ok := t.Children[car]; ok {
99 attrs = append(attrs, child.Applied(cdr)...)