Commit 57d671f
Eric Bower
·
2026-09-15 07:17:53 -0400 EDT
parent b93c126
fix: race when determining if file is text file
1 files changed,
+57,
-26
M
main.go
M
main.go
+57,
-26
| ... | ... | @@ -277,12 +277,14 @@ func (c *Config) parseText(filename string, text string) (string, error) { | |
| 277 | 277 | // that is, if it is likely that s is human-readable text. | |
| 278 | 278 | func isText(s string) bool { | |
| 279 | 279 | const max = 1024 // at least utf8.UTFMax | |
| 280 | + | truncated := false | |
| 280 | 281 | if len(s) > max { | |
| 281 | 282 | s = s[0:max] | |
| 283 | + | truncated = true | |
| 282 | 284 | } | |
| 283 | 285 | for i, c := range s { | |
| 284 | - | if i+utf8.UTFMax > len(s) { | |
| 285 | - | // last char may be incomplete - ignore | |
| 286 | + | if truncated && i+utf8.UTFMax > len(s) { | |
| 287 | + | // last char may be incomplete due to truncation - ignore | |
| 286 | 288 | break | |
| 287 | 289 | } | |
| 288 | 290 | if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' && c != '\r' { |
| ... | ... | @@ -326,12 +328,15 @@ var knownBinaryExts = newSet( | |
| 326 | 328 | var knownTextExts = newSet( | |
| 327 | 329 | // code | |
| 328 | 330 | ".go", ".py", ".js", ".ts", ".tsx", ".jsx", ".java", ".c", ".h", ".cpp", ".hpp", ".rs", ".rb", ".php", ".pl", ".sh", ".bash", ".zsh", ".fish", ".ps1", | |
| 331 | + | ".lua", ".swift", ".kt", ".kts", ".dart", ".zig", ".scala", ".ex", ".exs", ".erl", ".hs", ".clj", ".cljs", ".el", ".lisp", ".r", ".jl", | |
| 329 | 332 | // markup / data | |
| 330 | - | ".html", ".htm", ".css", ".scss", ".less", ".xml", ".json", ".yaml", ".yml", ".toml", ".ini", ".cfg", ".conf", | |
| 333 | + | ".html", ".htm", ".css", ".scss", ".less", ".xml", ".json", ".jsonl", ".yaml", ".yml", ".toml", ".ini", ".cfg", ".conf", | |
| 331 | 334 | // docs | |
| 332 | 335 | ".md", ".markdown", ".txt", ".rst", ".tex", ".bib", ".csv", ".tsv", | |
| 333 | 336 | // config / build | |
| 334 | - | ".Dockerfile", ".dockerignore", ".gitignore", ".gitattributes", ".editorconfig", | |
| 337 | + | ".dockerfile", ".dockerignore", ".gitignore", ".gitattributes", ".gitmodules", ".editorconfig", | |
| 338 | + | // templates / meta | |
| 339 | + | ".tmpl", ".template", ".mod", ".sum", ".env", ".lock", ".license", ".licence", ".copying", | |
| 335 | 340 | // other text | |
| 336 | 341 | ".diff", ".patch", ".log", ".sql", ".graphql", ".proto", ".makefile", ".cmake", | |
| 337 | 342 | ) |
| ... | ... | @@ -541,7 +546,11 @@ func (c *Config) writeHTMLTreeFile(pageData PageData, treeItem *TreeItem) string | |
| 541 | 546 | ||
| 542 | 547 | contents := "binary file, cannot display" | |
| 543 | 548 | if treeItem.IsTextFile { | |
| 544 | - | treeItem.NumLines = len(strings.Split(str, "\n")) | |
| 549 | + | if len(str) == 0 { | |
| 550 | + | treeItem.NumLines = 0 | |
| 551 | + | } else { | |
| 552 | + | treeItem.NumLines = len(strings.Split(strings.TrimSuffix(str, "\n"), "\n")) | |
| 553 | + | } | |
| 545 | 554 | if isMarkdown(treeItem.Entry.Name()) { | |
| 546 | 555 | html, err := ParseMarkdown(str) | |
| 547 | 556 | bail(err) |
| ... | ... | @@ -1141,6 +1150,7 @@ func (c *Config) writeRevision(repo *git.Repository, pageData *PageData, refs [] | |
| 1141 | 1150 | bail(err) | |
| 1142 | 1151 | ||
| 1143 | 1152 | readme := "" | |
| 1153 | + | var readmeMu sync.Mutex | |
| 1144 | 1154 | entries := make(chan *TreeItem) | |
| 1145 | 1155 | subtrees := make(chan *TreeRoot) | |
| 1146 | 1156 | tw := &TreeWalker{ |
| ... | ... | @@ -1150,42 +1160,63 @@ func (c *Config) writeRevision(repo *git.Repository, pageData *PageData, refs [] | |
| 1150 | 1160 | treeItem: entries, | |
| 1151 | 1161 | tree: subtrees, | |
| 1152 | 1162 | } | |
| 1153 | - | wg.Add(1) | |
| 1163 | + | ||
| 1164 | + | var twWg sync.WaitGroup | |
| 1165 | + | twWg.Add(1) | |
| 1154 | 1166 | go func() { | |
| 1155 | - | defer wg.Done() | |
| 1167 | + | defer twWg.Done() | |
| 1156 | 1168 | tw.walk(tree, "") | |
| 1157 | 1169 | }() | |
| 1158 | 1170 | ||
| 1159 | - | wg.Add(1) | |
| 1171 | + | var roots []*TreeRoot | |
| 1172 | + | var rootsMu sync.Mutex | |
| 1173 | + | var subtreeWg sync.WaitGroup | |
| 1174 | + | subtreeWg.Add(1) | |
| 1160 | 1175 | go func() { | |
| 1161 | - | defer wg.Done() | |
| 1176 | + | defer subtreeWg.Done() | |
| 1177 | + | for t := range subtrees { | |
| 1178 | + | rootsMu.Lock() | |
| 1179 | + | roots = append(roots, t) | |
| 1180 | + | rootsMu.Unlock() | |
| 1181 | + | } | |
| 1182 | + | }() | |
| 1183 | + | ||
| 1184 | + | var fileWg sync.WaitGroup | |
| 1185 | + | var entryWg sync.WaitGroup | |
| 1186 | + | entryWg.Add(1) | |
| 1187 | + | go func() { | |
| 1188 | + | defer entryWg.Done() | |
| 1162 | 1189 | for e := range entries { | |
| 1163 | - | wg.Add(1) | |
| 1190 | + | if e.IsDir { | |
| 1191 | + | continue | |
| 1192 | + | } | |
| 1193 | + | fileWg.Add(1) | |
| 1164 | 1194 | go func(entry *TreeItem) { | |
| 1165 | - | defer wg.Done() | |
| 1166 | - | if entry.IsDir { | |
| 1167 | - | return | |
| 1168 | - | } | |
| 1169 | - | ||
| 1195 | + | defer fileWg.Done() | |
| 1170 | 1196 | readmeStr := c.writeHTMLTreeFile(*pageData, entry) | |
| 1171 | 1197 | if readmeStr != "" { | |
| 1198 | + | readmeMu.Lock() | |
| 1172 | 1199 | readme = readmeStr | |
| 1200 | + | readmeMu.Unlock() | |
| 1173 | 1201 | } | |
| 1174 | 1202 | }(e) | |
| 1175 | 1203 | } | |
| 1176 | 1204 | }() | |
| 1177 | 1205 | ||
| 1178 | - | wg.Add(1) | |
| 1179 | - | go func() { | |
| 1180 | - | defer wg.Done() | |
| 1181 | - | for t := range subtrees { | |
| 1182 | - | wg.Add(1) | |
| 1183 | - | go func(tree *TreeRoot) { | |
| 1184 | - | defer wg.Done() | |
| 1185 | - | c.writeTree(*pageData, tree) | |
| 1186 | - | }(t) | |
| 1187 | - | } | |
| 1188 | - | }() | |
| 1206 | + | twWg.Wait() | |
| 1207 | + | subtreeWg.Wait() | |
| 1208 | + | entryWg.Wait() | |
| 1209 | + | fileWg.Wait() | |
| 1210 | + | ||
| 1211 | + | var treeWg sync.WaitGroup | |
| 1212 | + | for _, t := range roots { | |
| 1213 | + | treeWg.Add(1) | |
| 1214 | + | go func(tree *TreeRoot) { | |
| 1215 | + | defer treeWg.Done() | |
| 1216 | + | c.writeTree(*pageData, tree) | |
| 1217 | + | }(t) | |
| 1218 | + | } | |
| 1219 | + | treeWg.Wait() | |
| 1189 | 1220 | ||
| 1190 | 1221 | wg.Wait() | |
| 1191 | 1222 |