diff options
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 68 |
1 files changed, 45 insertions, 23 deletions
@@ -133,7 +133,7 @@ func buildWithFallback(root, canonicalRoot, fallback string, manageGitignore boo func excluded(rel string) bool { for _, part := range strings.Split(filepath.ToSlash(rel), "/") { - if strings.HasPrefix(part, "_") || part == ".git" || part == ".jj" || strings.HasPrefix(part, ".weft-txn-") { + if strings.HasPrefix(part, "_") || strings.HasPrefix(part, ".") { return true } } @@ -143,28 +143,7 @@ func excluded(rel string) bool { func (s *site) discover() error { outputs := map[string]string{} var templatePaths []string - err := filepath.WalkDir(s.root, func(full string, entry fs.DirEntry, walkErr error) error { - if walkErr != nil { - return walkErr - } - rel, err := filepath.Rel(s.root, full) - if err != nil || rel == "." { - return err - } - if excluded(rel) { - if entry.IsDir() { - return filepath.SkipDir - } - return nil - } - if entry.IsDir() { - return nil - } - rel = filepath.ToSlash(rel) - info, err := entry.Info() - if err != nil { - return err - } + err := walkFiles(s.root, func(rel string, info fs.FileInfo) error { switch { case strings.HasSuffix(rel, ".md"): out := strings.TrimSuffix(rel, ".md") + ".html" @@ -212,6 +191,49 @@ func (s *site) discover() error { return nil } +func walkFiles(root string, visit func(string, fs.FileInfo) error) error { + active := map[string]bool{} + var walk func(string, string) error + walk = func(full, relDir string) error { + real, err := filepath.EvalSymlinks(full) + if err != nil { + return err + } + if active[real] { + return fmt.Errorf("symlink cycle at %s", filepath.ToSlash(relDir)) + } + active[real] = true + defer delete(active, real) + + entries, err := os.ReadDir(full) + if err != nil { + return err + } + for _, entry := range entries { + rel := filepath.Join(relDir, entry.Name()) + if excluded(rel) { + continue + } + name := filepath.Join(full, entry.Name()) + info, err := os.Stat(name) + if err != nil { + return err + } + if info.IsDir() { + if err := walk(name, rel); err != nil { + return err + } + continue + } + if err := visit(filepath.ToSlash(rel), info); err != nil { + return err + } + } + return nil + } + return walk(root, "") +} + func claim(outputs map[string]string, output, input string) error { if previous, ok := outputs[output]; ok { return fmt.Errorf("output collision: %s and %s both target %s", previous, input, output) |
