Files
git-pages/src/gitattributes.go

62 lines
1.5 KiB
Go

package git_pages
import (
"bytes"
"cmp"
"context"
"slices"
"strings"
"github.com/go-git/go-git/v6/plumbing/format/gitattributes"
)
func ReadGitAttributes(ctx context.Context, manifest *Manifest) gitattributes.Matcher {
type entryPair struct {
parts []string
entry *Entry
}
// Collect all .gitattributes files.
var files []entryPair
for name, entry := range manifest.GetContents() {
switch entry.GetType() {
case Type_InlineFile, Type_ExternalFile:
parts := strings.Split(name, "/")
if parts[len(parts)-1] == ".gitattributes" {
files = append(files, entryPair{parts, entry})
}
}
}
// Sort the file list by depth, then by name.
slices.SortFunc(files, func(a entryPair, b entryPair) int {
return cmp.Or(
cmp.Compare(len(a.parts), len(b.parts)),
slices.Compare(a.parts, b.parts),
)
})
// Gather all .gitattributes rules, sorted by depth.
var rules []gitattributes.MatchAttribute
for _, pair := range files {
parts, entry := pair.parts, pair.entry
data, err := GetEntryContents(ctx, entry)
if err != nil {
continue
}
dirs := parts[:len(parts)-1]
isRoot := len(parts) == 1
newRules, err := gitattributes.ReadAttributes(bytes.NewReader(data), dirs, isRoot)
if err != nil {
AddProblem(manifest, strings.Join(parts, "/"), "parsing .gitattributes: %v", err)
continue
}
rules = append(rules, newRules...)
}
// gitattributes.Matcher applies rules in reverse.
slices.Reverse(rules)
matcher := gitattributes.NewMatcher(rules)
return matcher
}