package filecatalog import ( "context" "io/fs" "os" "path" "path/filepath" "sort" "strings" ) // FindYAMLFiles returns sorted full paths for .yaml and .yml files under root. func FindYAMLFiles(ctx context.Context, root string) ([]string, error) { var files []string err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error { if err != nil { return err } select { case <-ctx.Done(): return ctx.Err() default: } if d.IsDir() { return nil } if !IsYAMLFile(d.Name()) { return nil } files = append(files, path) return nil }) sort.Strings(files) return files, err } // FindFSYAMLFiles returns sorted paths for .yaml and .yml files under root in fsys. func FindFSYAMLFiles(ctx context.Context, fsys fs.FS, root string) ([]string, error) { cleanRoot := CleanFSRoot(root) var files []string err := fs.WalkDir(fsys, cleanRoot, func(name string, d fs.DirEntry, err error) error { if err != nil { return err } select { case <-ctx.Done(): return ctx.Err() default: } if d.IsDir() { return nil } if !IsYAMLFile(d.Name()) { return nil } files = append(files, name) return nil }) sort.Strings(files) return files, err } // RelativePath computes a clean relative path from root to path. func RelativePath(root string, filePath string) string { rel, err := filepath.Rel(root, filePath) if err != nil { return filepath.Clean(filePath) } return filepath.Clean(rel) } // CleanFSRoot normalizes a root path for use with fs.FS. func CleanFSRoot(root string) string { root = strings.TrimSpace(root) if root == "" || root == "." { return "." } return path.Clean(root) } // DisplayPath returns name relative to root for messages about fs.FS paths. func DisplayPath(root string, name string) string { cleanRoot := CleanFSRoot(root) cleanName := path.Clean(name) if cleanRoot == "." { return cleanName } prefix := strings.TrimSuffix(cleanRoot, "/") + "/" if strings.HasPrefix(cleanName, prefix) { return strings.TrimPrefix(cleanName, prefix) } return cleanName } // Stem strips .yaml or .yml from a file name. func Stem(name string) string { name = strings.TrimSuffix(name, ".yaml") name = strings.TrimSuffix(name, ".yml") return name } func IsYAMLFile(name string) bool { return strings.HasSuffix(name, ".yaml") || strings.HasSuffix(name, ".yml") }