From c1c8b4c3b732daad88c6364ffbec21dbc9408a8d Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Mon, 30 Oct 2023 13:02:39 +1100 Subject: [PATCH] refactor: switch to TBD54566975/scaffolder --- go.mod | 3 +- go.sum | 2 + internal/scaffolder.go | 127 +++++------------------------------------ 3 files changed, 19 insertions(+), 113 deletions(-) diff --git a/go.mod b/go.mod index 71c6ce4620..23632d1c7d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/TBD54566975/ftl -go 1.21 +go 1.21.3 require ( connectrpc.com/connect v1.11.1 @@ -59,6 +59,7 @@ require ( require ( connectrpc.com/grpcreflect v1.2.0 connectrpc.com/otelconnect v0.5.0 + github.com/TBD54566975/scaffolder v0.0.0-20231026011825-304b47f65b46 github.com/alecthomas/assert/v2 v2.3.0 github.com/alecthomas/atomic v0.1.0-alpha2 github.com/alecthomas/concurrency v0.0.2 diff --git a/go.sum b/go.sum index 6e65c438a0..201163f5f3 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ connectrpc.com/otelconnect v0.5.0 h1:K7xQKFbgeaHx563B+IIbd1EJe856AanueIYtGEtdnH8 connectrpc.com/otelconnect v0.5.0/go.mod h1:cjBMmtJmTokg4/k/3iDjLOjfNVM4qSVfIWz/qWQ8FNw= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/TBD54566975/scaffolder v0.0.0-20231026011825-304b47f65b46 h1:dy1l8sMkoRjVzKvBvozujrL9VNYw3G8H+Tb+EB/p+qs= +github.com/TBD54566975/scaffolder v0.0.0-20231026011825-304b47f65b46/go.mod h1:qQeIiuDDE901L32T7X/S36aIPdf4Qkxfm9qmF7+I2Wg= github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0= github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= diff --git a/internal/scaffolder.go b/internal/scaffolder.go index 3035e87ec3..d86bf22fcb 100644 --- a/internal/scaffolder.go +++ b/internal/scaffolder.go @@ -1,128 +1,31 @@ package internal import ( - "io/fs" - "os" - "path/filepath" "reflect" "strings" "text/template" "github.com/alecthomas/errors" "github.com/iancoleman/strcase" + + "github.com/TBD54566975/scaffolder" ) // Scaffold evaluates the scaffolding files at the given destination against // ctx. -// -// Both paths and file contents are evaluated. -// -// If a file name ends with ".tmpl", the ".tmpl" suffix is removed. -// -// The functions "snake", "camel", "lowerCamel", "kebab", "upper", and "lower" -// are available. -// -// This is inspired by [cookiecutter]. -// -// [cookiecutter]: https://github.com/cookiecutter/cookiecutter func Scaffold(destination string, ctx any) error { - return errors.WithStack(walkDir(destination, func(path string, d fs.DirEntry) error { - info, err := d.Info() - if err != nil { - return errors.WithStack(err) - } - - if strings.HasSuffix(path, ".tmpl") { - newPath := strings.TrimSuffix(path, ".tmpl") - if err = os.Rename(path, newPath); err != nil { - return errors.Wrap(err, "failed to rename file") - } - path = newPath - } - - // Evaluate the last component of path name templates. - dir := filepath.Dir(path) - base := filepath.Base(path) - newName, err := evaluate(base, ctx) - if err != nil { - return errors.Wrapf(err, "%s", path) - } - // Rename if necessary. - if newName != base { - newName = filepath.Join(dir, newName) - err = os.Rename(path, newName) - if err != nil { - return errors.Wrap(err, "failed to rename file") - } - path = newName - } - - if !info.Mode().IsRegular() { - return nil - } - - // Evaluate file content. - template, err := os.ReadFile(path) - if err != nil { - return errors.Wrapf(err, "%s", path) - } - content, err := evaluate(string(template), ctx) - if err != nil { - return errors.Wrapf(err, "%s", path) - } - err = os.WriteFile(path, []byte(content), info.Mode()) - if err != nil { - return errors.Wrapf(err, "%s", path) - } - return nil - })) -} - -// Walk dir executing fn after each entry. -func walkDir(dir string, fn func(path string, d fs.DirEntry) error) error { - entries, err := os.ReadDir(dir) - if err != nil { - return errors.WithStack(err) - } - for _, entry := range entries { - if entry.IsDir() { - err = walkDir(filepath.Join(dir, entry.Name()), fn) - if err != nil { - return errors.WithStack(err) - } - } - err = fn(filepath.Join(dir, entry.Name()), entry) - if err != nil { - return errors.WithStack(err) - } - } - return nil -} - -func evaluate(tmpl string, ctx any) (string, error) { - t, err := template.New("scaffolding").Funcs( - template.FuncMap{ - "snake": strcase.ToSnake, - "screamingSnake": strcase.ToScreamingSnake, - "camel": strcase.ToCamel, - "lowerCamel": strcase.ToLowerCamel, - "kebab": strcase.ToKebab, - "screamingKebab": strcase.ToScreamingKebab, - "upper": strings.ToUpper, - "lower": strings.ToLower, - "title": strings.Title, - "typename": func(v any) string { - return reflect.Indirect(reflect.ValueOf(v)).Type().Name() - }, + return errors.WithStack(scaffolder.Scaffold(destination, ctx, scaffolder.Functions(template.FuncMap{ + "snake": strcase.ToSnake, + "screamingSnake": strcase.ToScreamingSnake, + "camel": strcase.ToCamel, + "lowerCamel": strcase.ToLowerCamel, + "kebab": strcase.ToKebab, + "screamingKebab": strcase.ToScreamingKebab, + "upper": strings.ToUpper, + "lower": strings.ToLower, + "title": strings.Title, + "typename": func(v any) string { + return reflect.Indirect(reflect.ValueOf(v)).Type().Name() }, - ).Parse(tmpl) - if err != nil { - return "", errors.Wrap(err, "failed to parse template") - } - newName := &strings.Builder{} - err = t.Execute(newName, ctx) - if err != nil { - return "", errors.Wrap(err, "failed to execute template") - } - return newName.String(), nil + }))) }