summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go68
1 files changed, 45 insertions, 23 deletions
diff --git a/main.go b/main.go
index 7f49389..ec081ba 100644
--- a/main.go
+++ b/main.go
@@ -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)