added better error handling to render/render.go

This commit is contained in:
steven carpenter 2025-07-25 17:22:38 -04:00
parent 9e4d1a6a28
commit 69674ffaa7

View file

@ -7,71 +7,94 @@ import (
"strings" "strings"
"text/template" "text/template"
"specCon18/bubblewand/embed" "specCon18/bubblewand/embed" // Import embedded template files
"specCon18/bubblewand/internal/logger" "specCon18/bubblewand/internal/logger" // Import logger for logging output
) )
// ProgramData holds user-supplied template values // ProgramData holds user-supplied values for template substitution.
type ProgramData struct { type ProgramData struct {
ModName string ModName string // Module name
PackageName string PackageName string // Go package name
ProgramVersion string ProgramVersion string // Version string
ProgramDesc string ProgramDesc string // Description of the program
OutputDir string OutputDir string // Target output directory for rendered files
} }
// RenderTemplates renders embedded .tmpl files into outputDir // RenderTemplates renders embedded .tmpl files into outputDir
func RenderTemplates(data ProgramData, outputDir string, verbose bool) error { func RenderTemplates(data ProgramData, outputDir string, verbose bool) error {
var renderedFiles int var renderedFiles int // Count of successfully rendered files
// Walk through the embedded templates filesystem starting at "templates"
err := fs.WalkDir(embed.Templates, "templates", func(path string, d fs.DirEntry, err error) error { err := fs.WalkDir(embed.Templates, "templates", func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
// Log and return error encountered while walking the filesystem
logger.Log.Errorf("Error walking path %q: %v", path, err)
return err return err
} }
// Skip directories and files that do not end with ".tmpl"
if d.IsDir() || !strings.HasSuffix(d.Name(), ".tmpl") { if d.IsDir() || !strings.HasSuffix(d.Name(), ".tmpl") {
return nil return nil
} }
// Get relative path inside templates/ // Strip the "templates/" prefix from path and remove ".tmpl" extension
relPath := strings.TrimPrefix(path, "templates/") relPath := strings.TrimPrefix(path, "templates/")
outputPath := filepath.Join(outputDir, strings.TrimSuffix(relPath, ".tmpl")) outputPath := filepath.Join(outputDir, strings.TrimSuffix(relPath, ".tmpl"))
// Ensure the parent directory for the output file exists
if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
logger.Log.Errorf("Failed to create directory for %s: %v", outputPath, err)
return err return err
} }
// Read the embedded template file
tmplBytes, err := embed.Templates.ReadFile(path) tmplBytes, err := embed.Templates.ReadFile(path)
if err != nil { if err != nil {
logger.Log.Errorf("Failed to read template %s: %v", path, err)
return err return err
} }
// Parse the template content
tmpl, err := template.New(d.Name()).Parse(string(tmplBytes)) tmpl, err := template.New(d.Name()).Parse(string(tmplBytes))
if err != nil { if err != nil {
logger.Log.Errorf("Failed to parse template %s: %v", path, err)
return err return err
} }
// Create the output file for writing the rendered content
outFile, err := os.Create(outputPath) outFile, err := os.Create(outputPath)
if err != nil { if err != nil {
logger.Log.Errorf("Failed to create output file %s: %v", outputPath, err)
return err return err
} }
defer outFile.Close() defer outFile.Close()
// Log the render operation if verbose mode is enabled
if verbose { if verbose {
logger.Log.Infof("Rendering %s → %s", path, outputPath) logger.Log.Infof("Rendering %s → %s", path, outputPath)
} }
// Execute the template using the provided data and write to file
if err := tmpl.Execute(outFile, data); err != nil {
logger.Log.Errorf("Failed to execute template %s: %v", path, err)
return err
}
renderedFiles++ renderedFiles++
return tmpl.Execute(outFile, data) return nil
}) })
// If any error occurred during the walk/render process, log and return it
if err != nil { if err != nil {
logger.Log.Errorf("Template rendering failed: %v", err)
return err return err
} }
// If not verbose and at least one file was rendered, print a summary log
if !verbose && renderedFiles > 0 { if !verbose && renderedFiles > 0 {
logger.Log.Info("Rendering templates") logger.Log.Info("Rendering templates")
} }
return nil return nil // Success
} }