From 29d40648194fc5374fad497ed3fdb85046c9d72f Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Fri, 26 Apr 2024 12:54:21 -0400 Subject: [PATCH] Support app directories in all commands (#1061) * Support app directories in all commands Support multi-file app directories in remaining commands like `check`, `profile`, `lint`, etc. Note that `pixlet check` no longer supports the `-r` flag for recursively searching through a directory. This is because a single app can now contain subfolders with Starlark files, which should be checked and validated as part of the enclosing app. This change also removes spell-checking entirely. * Speed up app loading and checks * We were loading an applet by walking its entire source FS, but skipping any files outside of the root directory. Instead, just list and process the files in the root directory explicitly. * Move buildifier-based checks to the end of `pixlet check`, since they walk the entire directory tree. This means they won't run if there are any other errors, which are quicker to find. * Try to fix macOS build It can't find `webp/demux.h` any more for some reason. --- .github/workflows/main.yml | 22 ++++- .github/workflows/pull-request.yml | 22 ++++- cmd/check.go | 141 +++++++++++++++-------------- cmd/community/community.go | 1 - cmd/community/loadapp.go | 29 ++++-- cmd/community/spellcheck.go | 98 -------------------- cmd/community/validateicons.go | 39 ++++---- cmd/lint.go | 5 - cmd/profile.go | 33 ++++--- cmd/render.go | 12 +-- go.mod | 1 - go.sum | 10 -- icons/icons.go | 1 - runtime/applet.go | 27 +++--- 14 files changed, 188 insertions(+), 253 deletions(-) delete mode 100644 cmd/community/spellcheck.go diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0b7dd74cef..c39d32a076 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -80,10 +80,17 @@ jobs: - name: Build frontend run: npm run build - - name: Build + - name: Build Linux run: make build if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + - name: Build macOS + run: make build + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" + - name: Build Windows shell: msys2 {0} run: | @@ -91,9 +98,16 @@ jobs: make build if: matrix.os == 'windows-latest' - - name: Test + - name: Test Linux run: make test - if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + if: matrix.os == 'ubuntu-22.04' + + - name: Test macOS + run: make test + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Test Windows shell: msys2 {0} @@ -126,6 +140,8 @@ jobs: run: make release-macos env: PIXLET_VERSION: ${{ steps.vars.outputs.tag }} + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Build Release Windows if: matrix.os == 'windows-latest' diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 5c3e7c593f..0f22cb3939 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -78,9 +78,16 @@ jobs: - name: Build frontend run: npm run build - - name: Build + - name: Build Linux run: make build - if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + if: matrix.os == 'ubuntu-22.04' + + - name: Build macOS + run: make build + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Build Windows shell: msys2 {0} @@ -89,9 +96,16 @@ jobs: make build if: matrix.os == 'windows-latest' - - name: Test + - name: Test Linux + run: make test + if: matrix.os == 'ubuntu-22.04' + + - name: Test macOS run: make test - if: matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-latest' + if: matrix.os == 'macos-latest' + env: + LIBRARY_PATH: "/opt/homebrew/lib" + CGO_CPPFLAGS: "-I/opt/homebrew/include" - name: Test Windows shell: msys2 {0} diff --git a/cmd/check.go b/cmd/check.go index 25e4254650..61f8a48476 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -2,29 +2,32 @@ package cmd import ( "fmt" + "io/fs" "os" "path/filepath" "strings" "time" - "github.com/bazelbuild/buildtools/buildifier/utils" "github.com/fatih/color" "github.com/spf13/cobra" "tidbyt.dev/pixlet/cmd/community" "tidbyt.dev/pixlet/manifest" + "tidbyt.dev/pixlet/tools" ) const MaxRenderTime = 1000000000 // 1000ms -func init() { - CheckCmd.Flags().BoolVarP(&rflag, "recursive", "r", false, "find apps recursively") -} - var CheckCmd = &cobra.Command{ - Use: "check ...", - Example: ` pixlet check app.star`, - Short: "Checks if an app is ready to publish", - Long: `The check command runs a series of checks to ensure your app is ready + Use: "check ...", + Example: `pixlet check examples/clock`, + Short: "Check if an app is ready to publish", + Long: `Check if an app is ready to publish. + +The path argument should be the path to the Pixlet app to check. The +app can be a single file with the .star extension, or a directory +containing multiple Starlark files and resources. + +The check command runs a series of checks to ensure your app is ready to publish in the community repo. Every failed check will have a solution provided. If your app fails a check, try the provided solution and reach out on Discord if you get stuck.`, @@ -33,85 +36,59 @@ Discord if you get stuck.`, } func checkCmd(cmd *cobra.Command, args []string) error { - // Use the same logic as buildifier to find relevant Tidbyt apps. - apps := args - if rflag { - discovered, err := utils.ExpandDirectories(&args) + // check every path. + foundIssue := false + for _, path := range args { + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) if err != nil { - return fmt.Errorf("could not discover apps using recursive flag: %w", err) + return fmt.Errorf("failed to stat %s: %w", path, err) } - apps = discovered - } else { - for _, app := range apps { - if filepath.Ext(app) != ".star" { - return fmt.Errorf("only starlark source files or directories with the recursive flag are supported") - } - } - } - // TODO: this needs to be parallelized. + var fsys fs.FS + var baseDir string + if info.IsDir() { + fsys = os.DirFS(path) + baseDir = path + } else { + if !strings.HasSuffix(path, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", path) + } - // Check every app. - foundIssue := false - for _, app := range apps { - // Check app formatting. - dryRunFlag = true - err := formatCmd(cmd, []string{app}) - if err != nil { - foundIssue = true - failure(app, fmt.Errorf("app is not formatted correctly: %w", err), fmt.Sprintf("try `pixlet format %s`", app)) - continue + fsys = tools.NewSingleFileFS(path) + baseDir = filepath.Dir(path) } // Check if an app can load. - err = community.LoadApp(cmd, []string{app}) - if err != nil { - foundIssue = true - failure(app, fmt.Errorf("app failed to load: %w", err), "try `pixlet community load-app` and resolve any runtime issues") - continue - } - - // Check if app is linted. - outputFormat = "off" - err = lintCmd(cmd, []string{app}) + err = community.LoadApp(cmd, []string{path}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app has lint warnings: %w", err), fmt.Sprintf("try `pixlet lint --fix %s`", app)) + failure(path, fmt.Errorf("app failed to load: %w", err), "try `pixlet community load-app` and resolve any runtime issues") continue } // Ensure icons are valid. - err = community.ValidateIcons(cmd, []string{app}) + err = community.ValidateIcons(cmd, []string{path}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app has invalid icons: %w", err), "try `pixlet community list-icons` for the full list of valid icons") + failure(path, fmt.Errorf("app has invalid icons: %w", err), "try `pixlet community list-icons` for the full list of valid icons") continue } // Check app manifest exists - dir := filepath.Dir(app) - if !doesManifestExist(dir) { + if !doesManifestExist(baseDir) { foundIssue = true - failure(app, fmt.Errorf("couldn't find app manifest: %w", err), fmt.Sprintf("try `pixlet community create-manifest %s`", filepath.Join(dir, manifest.ManifestFileName))) + failure(path, fmt.Errorf("couldn't find app manifest"), fmt.Sprintf("try `pixlet community create-manifest %s`", filepath.Join(baseDir, manifest.ManifestFileName))) continue } // Validate manifest. - manifestFile := filepath.Join(dir, manifest.ManifestFileName) - community.ValidateManifestAppFileName = filepath.Base(app) + manifestFile := filepath.Join(baseDir, manifest.ManifestFileName) + community.ValidateManifestAppFileName = filepath.Base(path) err = community.ValidateManifest(cmd, []string{manifestFile}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("manifest didn't validate: %w", err), "try correcting the validation issue by updating your manifest") - continue - } - - // Check spelling. - community.SilentSpelling = true - err = community.SpellCheck(cmd, []string{manifestFile}) - if err != nil { - foundIssue = true - failure(app, fmt.Errorf("manifest contains spelling errors: %w", err), fmt.Sprintf("try `pixlet community spell-check --fix %s`", manifestFile)) + failure(path, fmt.Errorf("manifest didn't validate: %w", err), "try correcting the validation issue by updating your manifest") continue } @@ -125,26 +102,58 @@ func checkCmd(cmd *cobra.Command, args []string) error { // Check if app renders. silenceOutput = true output = f.Name() - err = render(cmd, []string{app}) + err = render(cmd, []string{path}) if err != nil { foundIssue = true - failure(app, fmt.Errorf("app failed to render: %w", err), "try `pixlet render` and resolve any runtime issues") + failure(path, fmt.Errorf("app failed to render: %w", err), "try `pixlet render` and resolve any runtime issues") continue } // Check performance. - p, err := ProfileApp(app, map[string]string{}) + p, err := ProfileApp(path, map[string]string{}) if err != nil { return fmt.Errorf("could not profile app: %w", err) } if p.DurationNanos > MaxRenderTime { foundIssue = true - failure(app, fmt.Errorf("app takes too long to render %s", time.Duration(p.DurationNanos)), fmt.Sprintf("try optimizing your app using `pixlet profile %s` to get it under %s", app, time.Duration(MaxRenderTime))) + failure( + path, + fmt.Errorf("app takes too long to render %s", time.Duration(p.DurationNanos)), + fmt.Sprintf("try optimizing your app using `pixlet profile %s` to get it under %s", path, time.Duration(MaxRenderTime)), + ) continue } + // run format and lint on *.star files in the fs + fs.WalkDir(fsys, ".", func(p string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() || !strings.HasSuffix(p, ".star") { + return nil + } + + realPath := filepath.Join(baseDir, p) + + dryRunFlag = true + if err := formatCmd(cmd, []string{realPath}); err != nil { + foundIssue = true + failure(p, fmt.Errorf("app is not formatted correctly: %w", err), fmt.Sprintf("try `pixlet format %s`", realPath)) + } + + outputFormat = "off" + err = lintCmd(cmd, []string{realPath}) + if err != nil { + foundIssue = true + failure(p, fmt.Errorf("app has lint warnings: %w", err), fmt.Sprintf("try `pixlet lint --fix %s`", realPath)) + } + + return nil + }) + // If we're here, the app and manifest are good to go! - success(app) + success(path) } if foundIssue { diff --git a/cmd/community/community.go b/cmd/community/community.go index aa8e3064ef..46c350e1c3 100644 --- a/cmd/community/community.go +++ b/cmd/community/community.go @@ -7,7 +7,6 @@ import ( func init() { CommunityCmd.AddCommand(ListIconsCmd) CommunityCmd.AddCommand(LoadAppCmd) - CommunityCmd.AddCommand(SpellCheckCmd) CommunityCmd.AddCommand(TargetDeterminatorCmd) CommunityCmd.AddCommand(ValidateIconsCmd) CommunityCmd.AddCommand(ValidateManifestCmd) diff --git a/cmd/community/loadapp.go b/cmd/community/loadapp.go index 8217976cb1..8fece80051 100644 --- a/cmd/community/loadapp.go +++ b/cmd/community/loadapp.go @@ -2,39 +2,50 @@ package community import ( "fmt" + "io/fs" "os" + "path/filepath" "strings" "github.com/spf13/cobra" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools" ) var LoadAppCmd = &cobra.Command{ - Use: "load-app ", + Use: "load-app ", Short: "Validates an app can be successfully loaded in our runtime.", - Example: ` pixlet community load-app app.star`, + Example: `pixlet community load-app examples/clock`, Long: `This command ensures an app can be loaded into our runtime successfully.`, Args: cobra.ExactArgs(1), RunE: LoadApp, } func LoadApp(cmd *cobra.Command, args []string) error { - script := args[0] + path := args[0] - if !strings.HasSuffix(script, ".star") { - return fmt.Errorf("script file must have suffix .star: %s", script) + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) + if err != nil { + return fmt.Errorf("failed to stat %s: %w", path, err) } - src, err := os.ReadFile(script) - if err != nil { - return fmt.Errorf("failed to read file %s: %w", script, err) + var fs fs.FS + if info.IsDir() { + fs = os.DirFS(path) + } else { + if !strings.HasSuffix(path, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", path) + } + + fs = tools.NewSingleFileFS(path) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - if _, err := runtime.NewApplet(script, src, runtime.WithPrintDisabled()); err != nil { + if _, err := runtime.NewAppletFromFS(filepath.Base(path), fs, runtime.WithPrintDisabled()); err != nil { return fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/community/spellcheck.go b/cmd/community/spellcheck.go deleted file mode 100644 index 1aebcd0c5f..0000000000 --- a/cmd/community/spellcheck.go +++ /dev/null @@ -1,98 +0,0 @@ -package community - -import ( - "fmt" - "io" - "os" - - "github.com/client9/misspell" - "github.com/spf13/cobra" -) - -var ( - FixSpelling bool - SilentSpelling bool -) - -func init() { - SpellCheckCmd.Flags().BoolVarP(&FixSpelling, "fix", "f", false, "fixes spelling mistakes automatically") - SpellCheckCmd.Flags().BoolVarP(&SilentSpelling, "silent", "s", false, "silences spelling mistakes") -} - -var SpellCheckCmd = &cobra.Command{ - Use: "spell-check ", - Short: "Spell check for a file", - Example: ` pixlet community spell-check manifest.yaml - pixlet community spell-check app.star`, - Long: `This command checks the spelling of strings located in a file. This can be used -both for a manifest and Tidbyt app.`, - Args: cobra.ExactArgs(1), - RunE: SpellCheck, -} - -func SpellCheck(cmd *cobra.Command, args []string) error { - // Load file for checking. - f, err := os.OpenFile(args[0], os.O_RDWR, 0644) - if err != nil { - return fmt.Errorf("could not open file: %w", err) - } - defer f.Close() - - b, err := io.ReadAll(f) - if err != nil { - return fmt.Errorf("could not read file: %w", err) - } - - // Create replacer. - r := misspell.Replacer{ - Replacements: misspell.DictMain, - } - - // Tidbyt is primarily in US markets. We only ship a US power plug, and all - // materials are in the US locale. In the future, we will need to consider - // how we manage spell check as we look to support more markets. - r.AddRuleList(misspell.DictAmerican) - r.Compile() - - // Run replacer. - updated, diffs := r.Replace(string(b)) - - // If FixSpelling is true, we only want to fix spelling and return - if FixSpelling { - // Updating a file in line gets a bit tricky. The file would first have - // to be cleared of the file contents, which feels dangerous. So - // instead, create a temp file, write the contents, and then replace - // the original file with the new file. - temp := args[0] + ".temp" - t, err := os.Create(temp) - if err != nil { - return fmt.Errorf("could not create file: %w", err) - } - defer t.Close() - - _, err = t.WriteString(updated) - if err != nil { - return fmt.Errorf("could not update file: %w", err) - } - - err = os.Rename(temp, args[0]) - if err != nil { - return fmt.Errorf("could not replace file: %w", err) - } - - return nil - } - - if !SilentSpelling { - for _, diff := range diffs { - fmt.Printf("`%s` is a misspelling of `%s` at line: %d\n", diff.Original, diff.Corrected, diff.Line) - } - } - - // Return error if there are any diffs. - if len(diffs) > 0 { - return fmt.Errorf("%s contains spelling errors", args[0]) - } - - return nil -} diff --git a/cmd/community/validateicons.go b/cmd/community/validateicons.go index f6d055afb1..d693995bd2 100644 --- a/cmd/community/validateicons.go +++ b/cmd/community/validateicons.go @@ -3,20 +3,22 @@ package community import ( "encoding/json" "fmt" - "io" + "io/fs" "os" + "path/filepath" + "strings" "github.com/spf13/cobra" - "go.starlark.net/starlark" "tidbyt.dev/pixlet/icons" "tidbyt.dev/pixlet/runtime" "tidbyt.dev/pixlet/schema" + "tidbyt.dev/pixlet/tools" ) var ValidateIconsCmd = &cobra.Command{ - Use: "validate-icons ", + Use: "validate-icons ", Short: "Validates the schema icons used are available in our mobile app.", - Example: ` pixlet community validate-icons app.star`, + Example: `pixlet community validate-icons examples/schema_hello_world`, Long: `This command determines if the icons selected in your app schema are supported by our mobile app.`, Args: cobra.ExactArgs(1), @@ -24,29 +26,30 @@ by our mobile app.`, } func ValidateIcons(cmd *cobra.Command, args []string) error { - f, err := os.Open(args[0]) + path := args[0] + + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) if err != nil { - return fmt.Errorf("couldn't open app: %w", err) + return fmt.Errorf("failed to stat %s: %w", path, err) } - defer f.Close() - src, err := io.ReadAll(f) - if err != nil { - return fmt.Errorf("failed to read app %s: %w", args[0], err) + var fs fs.FS + if info.IsDir() { + fs = os.DirFS(path) + } else { + if !strings.HasSuffix(path, ".star") { + return fmt.Errorf("script file must have suffix .star: %s", path) + } + + fs = tools.NewSingleFileFS(path) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - // Remove the print function from the starlark thread. - initializers := []runtime.ThreadInitializer{} - initializers = append(initializers, func(thread *starlark.Thread) *starlark.Thread { - thread.Print = func(thread *starlark.Thread, msg string) {} - return thread - }) - - applet, err := runtime.NewApplet(args[0], src, runtime.WithPrintDisabled()) + applet, err := runtime.NewAppletFromFS(filepath.Base(path), fs, runtime.WithPrintDisabled()) if err != nil { return fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/lint.go b/cmd/lint.go index eaec00b9ab..104507c48e 100644 --- a/cmd/lint.go +++ b/cmd/lint.go @@ -48,11 +48,6 @@ func lintCmd(cmd *cobra.Command, args []string) error { differ, _ := differ.Find() diff = differ - // TODO: We currently offer misspelling protection in the community repo - // for app manifests. We'll want to consider adding additional spelling - // support to pixlet lint to ensure typos in apps don't make it to - // production. - // Run buildifier and exit with the returned exit code. exitCode := runBuildifier(args, lint, mode, outputFormat, rflag, vflag) if exitCode != 0 { diff --git a/cmd/profile.go b/cmd/profile.go index 27d5a9b7e2..1a4d691d9b 100644 --- a/cmd/profile.go +++ b/cmd/profile.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "io/fs" "os" "strings" "time" @@ -14,6 +15,7 @@ import ( "go.starlark.net/starlark" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools" ) var ( @@ -27,8 +29,8 @@ func init() { } var ProfileCmd = &cobra.Command{ - Use: "profile [script] [=value>]...", - Short: "Run a Pixlet script and print its execution-time profile", + Use: "profile [=value>]...", + Short: "Run a Pixlet app and print its execution-time profile", Args: cobra.MinimumNArgs(1), RunE: profile, } @@ -65,11 +67,7 @@ func (u printUI) WantBrowser() bool { return false } func (u printUI) SetAutoComplete(complete func(string) string) {} func profile(cmd *cobra.Command, args []string) error { - script := args[0] - - if !strings.HasSuffix(script, ".star") { - return fmt.Errorf("script file must have suffix .star: %s", script) - } + path := args[0] config := map[string]string{} for _, param := range args[1:] { @@ -80,7 +78,7 @@ func profile(cmd *cobra.Command, args []string) error { config[split[0]] = split[1] } - profile, err := ProfileApp(script, config) + profile, err := ProfileApp(path, config) if err != nil { return err } @@ -96,17 +94,28 @@ func profile(cmd *cobra.Command, args []string) error { return nil } -func ProfileApp(script string, config map[string]string) (*pprof_profile.Profile, error) { - src, err := os.ReadFile(script) +func ProfileApp(path string, config map[string]string) (*pprof_profile.Profile, error) { + info, err := os.Stat(path) if err != nil { - return nil, fmt.Errorf("failed to read file %s: %w", script, err) + return nil, fmt.Errorf("failed to stat %s: %w", path, err) + } + + var fsys fs.FS + if info.IsDir() { + fsys = os.DirFS(path) + } else { + if !strings.HasSuffix(path, ".star") { + return nil, fmt.Errorf("script file must have suffix .star: %s", path) + } + + fsys = tools.NewSingleFileFS(path) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - applet, err := runtime.NewApplet(script, src, runtime.WithPrintDisabled()) + applet, err := runtime.NewAppletFromFS(path, fsys, runtime.WithPrintDisabled()) if err != nil { return nil, fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/render.go b/cmd/render.go index d64327c78c..e7c532c4c0 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "strings" - "testing/fstest" "time" "github.com/spf13/cobra" @@ -16,6 +15,7 @@ import ( "tidbyt.dev/pixlet/encode" "tidbyt.dev/pixlet/globals" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools" ) var ( @@ -102,15 +102,7 @@ func render(cmd *cobra.Command, args []string) error { return fmt.Errorf("script file must have suffix .star: %s", path) } - src, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read file %s: %w", path, err) - } - - fs = fstest.MapFS{ - filepath.Base(path): {Data: src}, - } - + fs = tools.NewSingleFileFS(path) outPath = strings.TrimSuffix(path, ".star") } diff --git a/go.mod b/go.mod index 962910d4b3..228bc50f82 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 github.com/antchfx/xmlquery v1.4.0 github.com/bazelbuild/buildtools v0.0.0-20230425225026-3dcc8d67e8ea - github.com/client9/misspell v0.3.4 github.com/dustin/go-humanize v1.0.1 github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 github.com/fatih/color v1.16.0 diff --git a/go.sum b/go.sum index e874881344..86b6fb1b2f 100644 --- a/go.sum +++ b/go.sum @@ -51,7 +51,6 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= @@ -90,8 +89,6 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -116,8 +113,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.1 h1:BSe8uhN+xQ4r5guV/ywQI4gO59C2raYcGffYWZEjZzM= -github.com/go-playground/validator/v10 v10.15.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -161,8 +156,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20240416155748-26353dc0451f h1:WpZiq8iqvGjJ3m3wzAVKL6+0vz7VkE79iSy9GII00II= -github.com/google/pprof v0.0.0-20240416155748-26353dc0451f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= @@ -202,8 +195,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -332,7 +323,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= diff --git a/icons/icons.go b/icons/icons.go index 1b4661eb8d..12f71f96b2 100644 --- a/icons/icons.go +++ b/icons/icons.go @@ -1,4 +1,3 @@ -//nolint:misspell package icons // IconsMap is the name of a FontAwesome icon to the name in our mobile app. In diff --git a/runtime/applet.go b/runtime/applet.go index 2bac67fe01..0c4ddddc5c 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -11,9 +11,9 @@ import ( "testing" "testing/fstest" + starlibbsoup "github.com/qri-io/starlib/bsoup" starlibgzip "github.com/qri-io/starlib/compress/gzip" starlibbase64 "github.com/qri-io/starlib/encoding/base64" - starlibbsoup "github.com/qri-io/starlib/bsoup" starlibcsv "github.com/qri-io/starlib/encoding/csv" starlibhash "github.com/qri-io/starlib/hash" starlibhtml "github.com/qri-io/starlib/html" @@ -311,24 +311,21 @@ func (a *Applet) PathsForBundle() []string { } func (a *Applet) load(fsys fs.FS) (err error) { - if err := fs.WalkDir(fsys, ".", func(pathToLoad string, d fs.DirEntry, walkDirErr error) error { - if walkDirErr != nil { - return walkDirErr - } + // list files in the root directory of fsys + rootDir, err := fs.ReadDir(fsys, ".") + if err != nil { + return fmt.Errorf("reading root directory: %v", err) + } - if d.IsDir() || path.Dir(pathToLoad) != "." { - // only process files in the root directory - return nil + for _, d := range rootDir { + if d.IsDir() || !strings.HasSuffix(d.Name(), ".star") { + // only process Starlark files + continue } - if !strings.HasSuffix(pathToLoad, ".star") { - // not a starlark file - return nil + if err := a.ensureLoaded(fsys, d.Name()); err != nil { + return err } - - return a.ensureLoaded(fsys, pathToLoad) - }); err != nil { - return err } if a.mainFun == nil {