[mirror] Scalable static site server for Git forges (like GitHub Pages)
at main 61 lines 1.5 kB view raw
1package git_pages 2 3import ( 4 "bytes" 5 "cmp" 6 "context" 7 "slices" 8 "strings" 9 10 "github.com/go-git/go-git/v6/plumbing/format/gitattributes" 11) 12 13func ReadGitAttributes(ctx context.Context, manifest *Manifest) gitattributes.Matcher { 14 type entryPair struct { 15 parts []string 16 entry *Entry 17 } 18 19 // Collect all .gitattributes files. 20 var files []entryPair 21 for name, entry := range manifest.GetContents() { 22 switch entry.GetType() { 23 case Type_InlineFile, Type_ExternalFile: 24 parts := strings.Split(name, "/") 25 if parts[len(parts)-1] == ".gitattributes" { 26 files = append(files, entryPair{parts, entry}) 27 } 28 } 29 } 30 31 // Sort the file list by depth, then by name. 32 slices.SortFunc(files, func(a entryPair, b entryPair) int { 33 return cmp.Or( 34 cmp.Compare(len(a.parts), len(b.parts)), 35 slices.Compare(a.parts, b.parts), 36 ) 37 }) 38 39 // Gather all .gitattributes rules, sorted by depth. 40 var rules []gitattributes.MatchAttribute 41 for _, pair := range files { 42 parts, entry := pair.parts, pair.entry 43 data, err := GetEntryContents(ctx, entry) 44 if err != nil { 45 continue 46 } 47 dirs := parts[:len(parts)-1] 48 isRoot := len(parts) == 1 49 newRules, err := gitattributes.ReadAttributes(bytes.NewReader(data), dirs, isRoot) 50 if err != nil { 51 AddProblem(manifest, strings.Join(parts, "/"), "parsing .gitattributes: %v", err) 52 continue 53 } 54 rules = append(rules, newRules...) 55 } 56 57 // gitattributes.Matcher applies rules in reverse. 58 slices.Reverse(rules) 59 matcher := gitattributes.NewMatcher(rules) 60 return matcher 61}