From 0eaca5c188229a804c2bc2afefc5dbdd76140757 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:28:13 +0000 Subject: [PATCH 01/19] fix(deps): update module golang.org/x/sync to v0.7.0 (#1029) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3347360b73..e947af7773 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( go.starlark.net v0.0.0-20240314022150-ee8ed142361c golang.org/x/image v0.15.0 golang.org/x/oauth2 v0.18.0 - golang.org/x/sync v0.5.0 + golang.org/x/sync v0.7.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index f9daeea868..f6d6aad1c8 100644 --- a/go.sum +++ b/go.sum @@ -702,6 +702,8 @@ golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From c4fe500b68b91729a3c85c85533bf07e80c09fa0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:08:12 +0000 Subject: [PATCH 02/19] fix(deps): update github.com/google/pprof digest to 29b9bb0 (#1032) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e947af7773..fd4a84b417 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gitsight/go-vcsurl v1.0.1 github.com/go-git/go-git/v5 v5.11.0 github.com/go-playground/validator/v10 v10.15.1 - github.com/google/pprof v0.0.0-20240327155427-868f304927ed + github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f github.com/google/tink/go v1.7.0 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 diff --git a/go.sum b/go.sum index f6d6aad1c8..194a6f3107 100644 --- a/go.sum +++ b/go.sum @@ -257,6 +257,8 @@ github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5X github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20240327155427-868f304927ed h1:n8QtJTrwsv3P7dNxPaMeNkMcxvUpqocsHLr8iDLGlQI= github.com/google/pprof v0.0.0-20240327155427-868f304927ed/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY= +github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= From dab5a190a43f5a75fb0f8847ca60aed88ad205f6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 22:13:56 +0000 Subject: [PATCH 03/19] fix(deps): update go.starlark.net digest to e6e8e7c (#1033) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index fd4a84b417..5daa2ac7aa 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/tidbyt/go-libwebp v0.0.0-20230922075150-fb11063b2a6a github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/zachomedia/go-bdf v0.0.0-20220611021443-a3af701111be - go.starlark.net v0.0.0-20240314022150-ee8ed142361c + go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a golang.org/x/image v0.15.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.7.0 diff --git a/go.sum b/go.sum index 194a6f3107..6fc2bf023e 100644 --- a/go.sum +++ b/go.sum @@ -537,6 +537,8 @@ go.starlark.net v0.0.0-20240307200823-981680b3e495 h1:Ln1SHdenasr/C6gJTSJcxc8L+l go.starlark.net v0.0.0-20240307200823-981680b3e495/go.mod h1:MrdO7XaMF3dE3MzuP6mrG0EB3NC7rLWSiEcu9Ii50g8= go.starlark.net v0.0.0-20240314022150-ee8ed142361c h1:roAjH18hZcwI4hHStHbkXjF5b7UUyZ/0SG3hXNN1SjA= go.starlark.net v0.0.0-20240314022150-ee8ed142361c/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= +go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a h1:Oe+v9w90BBIxQZ4U39+axR8KxrBbxqnRudPPcBIlP3o= +go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= From c9bc08920fbcc4950042f74a0603b682aa6bcf3e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 02:10:03 +0000 Subject: [PATCH 04/19] chore(deps): update dependency @babel/core to v7.24.4 (#1034) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 62 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index be63eb2d4d..9e79e316a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "react-simple-oauth2-login": "0.5.4" }, "devDependencies": { - "@babel/core": "7.24.3", + "@babel/core": "7.24.4", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/preset-react": "7.24.1", "@svgr/webpack": "6.5.1", @@ -102,18 +102,18 @@ } }, "node_modules/@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", + "@babel/generator": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", "@babel/template": "^7.24.0", "@babel/traverse": "^7.24.1", "@babel/types": "^7.24.0", @@ -138,9 +138,9 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, "dependencies": { "@babel/types": "^7.24.0", @@ -482,9 +482,9 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "dependencies": { "@babel/template": "^7.24.0", @@ -510,9 +510,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -8711,18 +8711,18 @@ "dev": true }, "@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", + "@babel/generator": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", "@babel/template": "^7.24.0", "@babel/traverse": "^7.24.1", "@babel/types": "^7.24.0", @@ -8742,9 +8742,9 @@ } }, "@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, "requires": { "@babel/types": "^7.24.0", @@ -9001,9 +9001,9 @@ } }, "@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "requires": { "@babel/template": "^7.24.0", @@ -9023,9 +9023,9 @@ } }, "@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { diff --git a/package.json b/package.json index 51fff92483..9b2c445b49 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "homepage": "https://github.com/tidbyt/pixlet#readme", "devDependencies": { - "@babel/core": "7.24.3", + "@babel/core": "7.24.4", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/preset-react": "7.24.1", "@svgr/webpack": "6.5.1", From 04919879945a9d65d42cd5209df254eec509c9e2 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Wed, 17 Apr 2024 13:54:43 -0400 Subject: [PATCH 05/19] Clean up applet initialization (#1036) * Clean up applet initialization * Previously you would a `runtime.Applet{}`, optionally set some fields on it, and then call its `Load` function. That function would set some other fields, and it was all kind of a mess. Replace all this with a `runtime.NewApplet()` function that accepts various options. * Get rid of the distinction between "filename" and "ID" for an applet. Each applet now only has an ID. * Replace Starlark thread initializers with explicit options or other alternatives. For example, `Run()` now accepts a `context.Context`, and there is a `WithPrintFunc` option. Minor: * Upgrade to Go 1.22.2. * Replace deprecated usages of `io/ioutil` and `pkg/errors`. * Fix lint errors * Add a function for running Starlark tests --- .github/workflows/main.yml | 6 +- .github/workflows/pull-request.yml | 4 +- cmd/community/loadapp.go | 16 +- cmd/community/validateicons.go | 5 +- cmd/profile.go | 16 +- cmd/render.go | 35 +- docs/gen_widget_imgs.go | 14 +- docs/schema/location/example.star | 2 +- docs/schema/locationbased/example.star | 2 +- docs/schema/oauth2/example.star | 2 +- docs/schema/photoselect/example.star | 2 +- encode/encode.go | 4 +- encode/encode_bench_test.go | 7 +- encode/encode_test.go | 33 +- encode/gif.go | 3 +- encode/webp.go | 8 +- examples/bitcoin.star | 4 +- examples/humanize.star | 2 +- examples/qrcode.star | 2 +- examples/sunrise.star | 4 +- go.mod | 8 +- go.sum | 485 +----------------- runtime/applet.go | 227 +++++--- runtime/applet_test.go | 108 ++-- runtime/cache_test.go | 37 +- runtime/httpcache.go | 3 +- runtime/httpcache_test.go | 7 +- runtime/modules/hmac/hmac_test.go | 7 +- runtime/modules/humanize/humanize_test.go | 7 +- runtime/modules/qrcode/qrcode_test.go | 6 +- runtime/modules/random/random.go | 1 - runtime/modules/random/random_test.go | 6 +- .../modules/starlarkhttp/testdata/test.star | 2 +- runtime/modules/sunrise/sunrise_test.go | 6 +- runtime/modules/xpath/xpath_test.go | 6 +- runtime/render_test.go | 21 +- runtime/secret.go | 15 +- runtime/secret_test.go | 17 +- runtime/test.star | 2 +- runtime/testdata/httpcache.star | 4 +- schema/color_test.go | 43 +- schema/datetime_test.go | 6 +- schema/dropdown_test.go | 6 +- schema/generated_test.go | 6 +- schema/handler_test.go | 19 +- schema/location_test.go | 6 +- schema/locationbased_test.go | 6 +- schema/module_test.go | 11 +- schema/oauth2_test.go | 6 +- schema/option_test.go | 6 +- schema/photoselect_test.go | 6 +- schema/schema_test.go | 9 +- schema/text_test.go | 6 +- schema/toggle_test.go | 6 +- schema/typeahead_test.go | 6 +- server/loader/loader.go | 27 +- server/loader/script.go | 15 +- server/loader/script_js.go | 17 +- 58 files changed, 437 insertions(+), 916 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3479704230..4f632823a4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.21" + go-version: "1.22.2" - name: Install buildifier run: make install-buildifier @@ -36,7 +36,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: "1.21" + go-version: "1.22.2" - name: Install Node uses: actions/setup-node@v3 @@ -158,7 +158,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: "1.21" + go-version: "1.22.2" - name: Fetch Release Artifacts uses: actions/download-artifact@v3 diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index fa82500a69..0a971b1493 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.21" + go-version: "1.22.2" - name: Install buildifier run: make install-buildifier @@ -34,7 +34,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: "1.21" + go-version: "1.22.2" - name: Install Node uses: actions/setup-node@v3 diff --git a/cmd/community/loadapp.go b/cmd/community/loadapp.go index b26ad1d437..8217976cb1 100644 --- a/cmd/community/loadapp.go +++ b/cmd/community/loadapp.go @@ -2,11 +2,10 @@ package community import ( "fmt" - "io/ioutil" + "os" "strings" "github.com/spf13/cobra" - "go.starlark.net/starlark" "tidbyt.dev/pixlet/runtime" ) @@ -26,7 +25,7 @@ func LoadApp(cmd *cobra.Command, args []string) error { return fmt.Errorf("script file must have suffix .star: %s", script) } - src, err := ioutil.ReadFile(script) + src, err := os.ReadFile(script) if err != nil { return fmt.Errorf("failed to read file %s: %w", script, err) } @@ -35,16 +34,7 @@ func LoadApp(cmd *cobra.Command, args []string) error { 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 := runtime.Applet{} - err = applet.LoadWithInitializers("", script, src, nil, initializers...) - if err != nil { + if _, err := runtime.NewApplet(script, src, runtime.WithPrintDisabled()); err != nil { return fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/community/validateicons.go b/cmd/community/validateicons.go index 3c654f62ad..f6d055afb1 100644 --- a/cmd/community/validateicons.go +++ b/cmd/community/validateicons.go @@ -46,8 +46,7 @@ func ValidateIcons(cmd *cobra.Command, args []string) error { return thread }) - applet := runtime.Applet{} - err = applet.LoadWithInitializers("", args[0], src, nil, initializers...) + applet, err := runtime.NewApplet(args[0], src, runtime.WithPrintDisabled()) if err != nil { return fmt.Errorf("failed to load applet: %w", err) } @@ -69,7 +68,7 @@ func ValidateIcons(cmd *cobra.Command, args []string) error { } if _, ok := icons.IconsMap[field.Icon]; !ok { - return fmt.Errorf("app '%s' contains unknown icon: '%s'", applet.Filename, field.Icon) + return fmt.Errorf("app '%s' contains unknown icon: '%s'", applet.ID, field.Icon) } } diff --git a/cmd/profile.go b/cmd/profile.go index 406b34f458..27d5a9b7e2 100644 --- a/cmd/profile.go +++ b/cmd/profile.go @@ -2,8 +2,8 @@ package cmd import ( "bytes" + "context" "fmt" - "io/ioutil" "os" "strings" "time" @@ -97,7 +97,7 @@ func profile(cmd *cobra.Command, args []string) error { } func ProfileApp(script string, config map[string]string) (*pprof_profile.Profile, error) { - src, err := ioutil.ReadFile(script) + src, err := os.ReadFile(script) if err != nil { return nil, fmt.Errorf("failed to read file %s: %w", script, err) } @@ -106,15 +106,7 @@ func ProfileApp(script string, config map[string]string) (*pprof_profile.Profile 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 := runtime.Applet{} - err = applet.LoadWithInitializers("", script, src, nil, initializers...) + applet, err := runtime.NewApplet(script, src, runtime.WithPrintDisabled()) if err != nil { return nil, fmt.Errorf("failed to load applet: %w", err) } @@ -124,7 +116,7 @@ func ProfileApp(script string, config map[string]string) (*pprof_profile.Profile return nil, fmt.Errorf("error starting profiler: %w", err) } - _, err = applet.Run(config, initializers...) + _, err = applet.RunWithConfig(context.Background(), config) if err != nil { _ = starlark.StopProfile() return nil, fmt.Errorf("error running script: %w", err) diff --git a/cmd/render.go b/cmd/render.go index 004facf77e..d5746ea5ec 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -4,18 +4,15 @@ import ( "context" "fmt" "image" - "io/ioutil" "os" "strings" "time" "github.com/spf13/cobra" - "go.starlark.net/starlark" "tidbyt.dev/pixlet/encode" "tidbyt.dev/pixlet/globals" "tidbyt.dev/pixlet/runtime" - "tidbyt.dev/pixlet/starlarkutil" ) var ( @@ -106,45 +103,37 @@ func render(cmd *cobra.Command, args []string) error { config[split[0]] = strings.Join(split[1:], "=") } - src, err := ioutil.ReadFile(script) + src, err := os.ReadFile(script) if err != nil { return fmt.Errorf("failed to read file %s: %w", script, err) } // Remove the print function from the starlark thread if the silent flag is // passed. - initializers := []runtime.ThreadInitializer{} + var opts []runtime.AppletOption if silenceOutput { - initializers = append(initializers, func(thread *starlark.Thread) *starlark.Thread { - thread.Print = func(thread *starlark.Thread, msg string) {} - return thread - }) + opts = append(opts, runtime.WithPrintDisabled()) } - // Timeout? + ctx := context.Background() if timeout > 0 { - initializers = append(initializers, func(thread *starlark.Thread) *starlark.Thread { - ctx, _ := context.WithTimeoutCause( - context.Background(), - time.Duration(timeout)*time.Millisecond, - fmt.Errorf("timeout after %dms", timeout), - ) - starlarkutil.AttachThreadContext(ctx, thread) - return thread - }) + ctx, _ = context.WithTimeoutCause( + ctx, + time.Duration(timeout)*time.Millisecond, + fmt.Errorf("timeout after %dms", timeout), + ) } cache := runtime.NewInMemoryCache() runtime.InitHTTP(cache) runtime.InitCache(cache) - applet := runtime.Applet{} - err = applet.LoadWithInitializers("", script, src, nil, initializers...) + applet, err := runtime.NewApplet(script, src, opts...) if err != nil { return fmt.Errorf("failed to load applet: %w", err) } - roots, err := applet.Run(config, initializers...) + roots, err := applet.RunWithConfig(ctx, config) if err != nil { return fmt.Errorf("error running script: %w", err) } @@ -200,7 +189,7 @@ func render(cmd *cobra.Command, args []string) error { if outPath == "-" { _, err = os.Stdout.Write(buf) } else { - err = ioutil.WriteFile(outPath, buf, 0644) + err = os.WriteFile(outPath, buf, 0644) } if err != nil { diff --git a/docs/gen_widget_imgs.go b/docs/gen_widget_imgs.go index b3d82f6fba..4865ac7dc7 100644 --- a/docs/gen_widget_imgs.go +++ b/docs/gen_widget_imgs.go @@ -4,9 +4,10 @@ package main // documentation. import ( + "context" "fmt" "image" - "io/ioutil" + "os" "strings" "tidbyt.dev/pixlet/encode" @@ -40,7 +41,7 @@ func Magnify(input image.Image) (image.Image, error) { } func main() { - files, err := ioutil.ReadDir(".") + files, err := os.ReadDir(".") if err != nil { panic(err) } @@ -51,7 +52,7 @@ func main() { continue } - content, err := ioutil.ReadFile(f.Name()) + content, err := os.ReadFile(f.Name()) if err != nil { panic(err) } @@ -67,13 +68,12 @@ def main(): return render.Root(child=w) `, snippet) - app := runtime.Applet{} - err = app.Load(fmt.Sprintf("id-%s", name), name, []byte(src), nil) + app, err := runtime.NewApplet(name, []byte(src)) if err != nil { panic(err) } - roots, err := app.Run(nil) + roots, err := app.Run(context.Background()) if err != nil { panic(err) } @@ -83,7 +83,7 @@ def main(): panic(err) } - err = ioutil.WriteFile(fmt.Sprintf("img/widget_%s.gif", name), gif, 0644) + err = os.WriteFile(fmt.Sprintf("img/widget_%s.gif", name), gif, 0644) if err != nil { panic(err) } diff --git a/docs/schema/location/example.star b/docs/schema/location/example.star index 32cde8c856..636d80df41 100644 --- a/docs/schema/location/example.star +++ b/docs/schema/location/example.star @@ -1,6 +1,6 @@ +load("encoding/json.star", "json") load("render.star", "render") load("schema.star", "schema") -load("encoding/json.star", "json") DEFAULT_LOCATION = """ { diff --git a/docs/schema/locationbased/example.star b/docs/schema/locationbased/example.star index 973bb400a8..10fc2884da 100644 --- a/docs/schema/locationbased/example.star +++ b/docs/schema/locationbased/example.star @@ -1,6 +1,6 @@ +load("encoding/json.star", "json") load("render.star", "render") load("schema.star", "schema") -load("encoding/json.star", "json") EXAMPLE_LOCATION = """ { diff --git a/docs/schema/oauth2/example.star b/docs/schema/oauth2/example.star index 45c6f793bf..19c8fd80cb 100644 --- a/docs/schema/oauth2/example.star +++ b/docs/schema/oauth2/example.star @@ -1,8 +1,8 @@ +load("encoding/json.star", "json") load("http.star", "http") load("render.star", "render") load("schema.star", "schema") load("secret.star", "secret") -load("encoding/json.star", "json") OAUTH2_CLIENT_SECRET = secret.decrypt("your-client-secret") diff --git a/docs/schema/photoselect/example.star b/docs/schema/photoselect/example.star index 487ebf8ea3..34db4002a7 100644 --- a/docs/schema/photoselect/example.star +++ b/docs/schema/photoselect/example.star @@ -1,6 +1,6 @@ +load("encoding/base64.star", "base64") load("render.star", "render") load("schema.star", "schema") -load("encoding/base64.star", "base64") def main(config): encoded = config.get("photo", DEFAULT_PHOTO) diff --git a/encode/encode.go b/encode/encode.go index 239b973000..7fde7ddce5 100644 --- a/encode/encode.go +++ b/encode/encode.go @@ -2,9 +2,9 @@ package encode import ( "crypto/sha256" + "fmt" "image" - "github.com/pkg/errors" "github.com/vmihailenco/msgpack/v5" "tidbyt.dev/pixlet/render" @@ -77,7 +77,7 @@ func (s *Screens) Hash() ([]byte, error) { j, err := msgpack.Marshal(hashable) if err != nil { - return nil, errors.Wrap(err, "marshaling render tree to JSON") + return nil, fmt.Errorf("marshaling render tree to JSON: %w", err) } h := sha256.Sum256(j) diff --git a/encode/encode_bench_test.go b/encode/encode_bench_test.go index c74c1aac3c..c75d350af9 100644 --- a/encode/encode_bench_test.go +++ b/encode/encode_bench_test.go @@ -1,6 +1,7 @@ package encode import ( + "context" "testing" "tidbyt.dev/pixlet/runtime" @@ -71,15 +72,13 @@ def main(config): ` func BenchmarkRunAndRender(b *testing.B) { - app := &runtime.Applet{} - err := app.Load("benchid", "benchmark.star", []byte(BenchmarkDotStar), nil) + app, err := runtime.NewApplet("benchmark.star", []byte(BenchmarkDotStar)) if err != nil { b.Error(err) } - config := map[string]string{} for i := 0; i < b.N; i++ { - roots, err := app.Run(config) + roots, err := app.Run(context.Background()) if err != nil { b.Error(err) } diff --git a/encode/encode_test.go b/encode/encode_test.go index 0f63c96b37..44633a3449 100644 --- a/encode/encode_test.go +++ b/encode/encode_test.go @@ -2,6 +2,7 @@ package encode import ( "bytes" + "context" "image/gif" "strings" "testing" @@ -144,11 +145,10 @@ def main(): ` func TestFile(t *testing.T) { - app := runtime.Applet{} - err := app.Load("testid", "test.star", []byte(TestDotStar), nil) + app, err := runtime.NewApplet("test.star", []byte(TestDotStar)) assert.NoError(t, err) - roots, err := app.Run(map[string]string{}) + roots, err := app.Run(context.Background()) assert.NoError(t, err) webp, err := ScreensFromRoots(roots).EncodeWebP(15000) @@ -157,11 +157,10 @@ func TestFile(t *testing.T) { } func TestHash(t *testing.T) { - app := runtime.Applet{} - err := app.Load("testid", "test.star", []byte(TestDotStar), nil) + app, err := runtime.NewApplet("test.star", []byte(TestDotStar)) require.NoError(t, err) - roots, err := app.Run(map[string]string{}) + roots, err := app.Run(context.Background()) require.NoError(t, err) // ensure we can calculate a hash @@ -178,11 +177,10 @@ func TestHash(t *testing.T) { // change the app slightly modifiedSource := strings.Replace(TestDotStar, "foo bar", "bar foo", 1) - app2 := runtime.Applet{} - err = app2.Load("testid2", "test.star", []byte(modifiedSource), nil) + app2, err := runtime.NewApplet("test.star", []byte(modifiedSource)) require.NoError(t, err) - roots2, err := app2.Run(map[string]string{}) + roots2, err := app2.Run(context.Background()) require.NoError(t, err) // ensure we can calculate a hash on the new app @@ -237,9 +235,9 @@ load("render.star", "render") def main(): return render.Root(show_full_animation=True, child=render.Box()) ` - app := runtime.Applet{} - require.NoError(t, app.Load("testid", "test.star", []byte(requestFull), nil)) - roots, err := app.Run(map[string]string{}) + app, err := runtime.NewApplet("test.star", []byte(requestFull)) + require.NoError(t, err) + roots, err := app.Run(context.Background()) assert.NoError(t, err) assert.True(t, ScreensFromRoots(roots).ShowFullAnimation) @@ -248,9 +246,9 @@ load("render.star", "render") def main(): return render.Root(child=render.Box()) ` - app = runtime.Applet{} - require.NoError(t, app.Load("testid", "test.star", []byte(dontRequestFull), nil)) - roots, err = app.Run(map[string]string{}) + app, err = runtime.NewApplet("test.star", []byte(dontRequestFull)) + require.NoError(t, err) + roots, err = app.Run(context.Background()) assert.NoError(t, err) assert.False(t, ScreensFromRoots(roots).ShowFullAnimation) } @@ -275,11 +273,10 @@ def main(): ) `) - app := runtime.Applet{} - err := app.Load("testid", "test.star", src, nil) + app, err := runtime.NewApplet("test.star", src) assert.NoError(t, err) - roots, err := app.Run(map[string]string{}) + roots, err := app.Run(context.Background()) assert.NoError(t, err) // Source above will produce a 70 frame animation diff --git a/encode/gif.go b/encode/gif.go index 3b8a162613..fa4dc4ab67 100644 --- a/encode/gif.go +++ b/encode/gif.go @@ -9,7 +9,6 @@ import ( "image/gif" "github.com/ericpauley/go-quantize/quantize" - "github.com/pkg/errors" ) // Renders a screen to GIF. Optionally pass filters for postprocessing @@ -56,7 +55,7 @@ func (s *Screens) EncodeGIF(maxDuration int, filters ...ImageFilter) ([]byte, er buf := &bytes.Buffer{} err = gif.EncodeAll(buf, g) if err != nil { - return nil, errors.Wrap(err, "encoding") + return nil, fmt.Errorf("encoding: %w", err) } return buf.Bytes(), nil diff --git a/encode/webp.go b/encode/webp.go index 9ad09a6e1b..fb3586e1e5 100644 --- a/encode/webp.go +++ b/encode/webp.go @@ -3,9 +3,9 @@ package encode import ( + "fmt" "time" - "github.com/pkg/errors" "github.com/tidbyt/go-libwebp/webp" ) @@ -29,7 +29,7 @@ func (s *Screens) EncodeWebP(maxDuration int, filters ...ImageFilter) ([]byte, e WebPKMax, ) if err != nil { - return nil, errors.Wrap(err, "initializing encoder") + return nil, fmt.Errorf("%s: %w", "initializing encoder", err) } defer anim.Close() @@ -45,7 +45,7 @@ func (s *Screens) EncodeWebP(maxDuration int, filters ...ImageFilter) ([]byte, e } if err := anim.AddFrame(im, frameDuration); err != nil { - return nil, errors.Wrap(err, "adding frame") + return nil, fmt.Errorf("%s: %w", "adding frame", err) } if maxDuration > 0 && remainingDuration <= 0 { @@ -55,7 +55,7 @@ func (s *Screens) EncodeWebP(maxDuration int, filters ...ImageFilter) ([]byte, e buf, err := anim.Assemble() if err != nil { - return nil, errors.Wrap(err, "encoding animation") + return nil, fmt.Errorf("%s: %w", "encoding animation", err) } return buf, nil diff --git a/examples/bitcoin.star b/examples/bitcoin.star index 3a3798b8df..19ea6748a1 100644 --- a/examples/bitcoin.star +++ b/examples/bitcoin.star @@ -1,6 +1,6 @@ -load("render.star", "render") -load("http.star", "http") load("encoding/base64.star", "base64") +load("http.star", "http") +load("render.star", "render") COINDESK_PRICE_URL = "https://api.coindesk.com/v1/bpi/currentprice.json" diff --git a/examples/humanize.star b/examples/humanize.star index 90197c0719..e021a1e93e 100644 --- a/examples/humanize.star +++ b/examples/humanize.star @@ -1,7 +1,7 @@ +load("humanize.star", "humanize") load("render.star", "render") load("schema.star", "schema") load("time.star", "time") -load("humanize.star", "humanize") DEFAULT_COUNTER = "1337" DEFAULT_APPS = "42" diff --git a/examples/qrcode.star b/examples/qrcode.star index 6b54e8d8dc..f812d3f94c 100644 --- a/examples/qrcode.star +++ b/examples/qrcode.star @@ -1,7 +1,7 @@ load("cache.star", "cache") load("encoding/base64.star", "base64") -load("render.star", "render") load("qrcode.star", "qrcode") +load("render.star", "render") def main(config): url = "https://tidbyt.com?utm_source=pixlet_example" diff --git a/examples/sunrise.star b/examples/sunrise.star index 6f70b8fb2b..f920309a30 100644 --- a/examples/sunrise.star +++ b/examples/sunrise.star @@ -1,8 +1,8 @@ +load("encoding/json.star", "json") load("render.star", "render") load("schema.star", "schema") -load("time.star", "time") -load("encoding/json.star", "json") load("sunrise.star", "sunrise") +load("time.star", "time") DEFAULT_LOCATION = """ { diff --git a/go.mod b/go.mod index 5daa2ac7aa..317e8c198c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module tidbyt.dev/pixlet -go 1.21 +go 1.22 + +toolchain go1.22.2 require ( github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 @@ -26,7 +28,6 @@ require ( github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c github.com/nlepage/go-wasm-http-server v1.1.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/pkg/errors v0.9.1 github.com/qri-io/starlib v0.5.1-0.20220611014110-7fb7ff9ec804 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/spf13/cobra v1.8.0 @@ -52,7 +53,6 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/PuerkitoBio/goquery v1.5.1 // indirect - github.com/acomagu/bufpipe v1.0.4 // indirect github.com/andybalholm/cascadia v1.1.0 // indirect github.com/antchfx/xpath v1.2.4 // indirect github.com/chzyer/readline v1.5.1 // indirect @@ -82,6 +82,7 @@ require ( github.com/nlepage/go-js-promise v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -91,7 +92,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index 6fc2bf023e..e9dd98c443 100644 --- a/go.sum +++ b/go.sum @@ -1,46 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 h1:y80Hd9hmB+rsEH/p4c5ti5PbO0PhBmxw4NgbpFZvoHg= github.com/Code-Hex/Neo-cowsay/v2 v2.0.4/go.mod h1:6k40Pwrc2FazLf1BUbmAC36E9LvT+DErjZr30isbXhg= github.com/Code-Hex/go-wordwrap v1.0.0 h1:yl5fLyZEz3+hPGbpTRlTQ8mQJ1HXWcTq1FCNR1ch6zM= @@ -53,16 +15,12 @@ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCv github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= -github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antchfx/xmlquery v1.3.16 h1:OCevguHq93z9Y4vb9xpRmU4Cc9lMVoiMkMbBNZVDeBM= -github.com/antchfx/xmlquery v1.3.16/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7TunF7noreA= github.com/antchfx/xmlquery v1.3.18 h1:FSQ3wMuphnPPGJOFhvc+cRQ2CT/rUj4cyQXkJcjOwz0= github.com/antchfx/xmlquery v1.3.18/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7TunF7noreA= github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY= @@ -97,21 +55,16 @@ github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -124,23 +77,15 @@ github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcej github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU= github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= 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= @@ -154,17 +99,10 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= -github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= -github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= -github.com/go-git/go-git/v5 v5.10.0 h1:F0x3xXrAWmhwtzoCokU4IMPcBdncG+HAAqi9FcOOjbQ= -github.com/go-git/go-git/v5 v5.10.0/go.mod h1:1FOZ/pQnqw24ghP2n7cunVl0ON55BsjPYvhWHvZGhoo= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -190,102 +128,47 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= -github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20240327155427-868f304927ed h1:n8QtJTrwsv3P7dNxPaMeNkMcxvUpqocsHLr8iDLGlQI= -github.com/google/pprof v0.0.0-20240327155427-868f304927ed/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +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-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY= github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE= github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -296,8 +179,6 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -305,7 +186,6 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -323,13 +203,9 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= -github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -362,22 +238,16 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/paulmach/orb v0.1.5/go.mod h1:pPwxxs3zoAyosNSbNKn1jiXV2+oovRDObDKfTvRegDI= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -396,13 +266,10 @@ github.com/qri-io/starlib v0.5.1-0.20220611014110-7fb7ff9ec804/go.mod h1:Geq0MWa github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= -github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -414,8 +281,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= -github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= @@ -425,33 +290,19 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= -github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= -github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= -github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= @@ -467,32 +318,20 @@ github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnR github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 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= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tidbyt/gg v0.0.0-20220808163829-95806fa1d427 h1:br5WYVw/jr4G0PZpBBx2fBAANVUrI8KKHMSs3LVqO9A= github.com/tidbyt/gg v0.0.0-20220808163829-95806fa1d427/go.mod h1:+SCm6iJHe2lfsQzlbLCsd5XsTKYSD0VqtQmWMnNs9OE= -github.com/tidbyt/go-libwebp v0.0.0-20220802221933-1fabc3b46601 h1:W7xhAgRtepnWBTmbzb0R+5ikjEYCX1c55SN8HJv5FcI= -github.com/tidbyt/go-libwebp v0.0.0-20220802221933-1fabc3b46601/go.mod h1:JU6yp7mldR7lmftjHPtaDs+Q8xn7l2tMR1XYx5iJELg= github.com/tidbyt/go-libwebp v0.0.0-20230922075150-fb11063b2a6a h1:zvAhEO3ZB7m1Lc3BwJXLTDrLrHVAbcDByJ7XkL4WR+s= github.com/tidbyt/go-libwebp v0.0.0-20230922075150-fb11063b2a6a/go.mod h1:JU6yp7mldR7lmftjHPtaDs+Q8xn7l2tMR1XYx5iJELg= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= -github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= -github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -501,42 +340,12 @@ github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zachomedia/go-bdf v0.0.0-20220611021443-a3af701111be h1:qf05vm7CJA3tcnR42pv2a/+pvCPGylJcg10B9CRFPvg= github.com/zachomedia/go-bdf v0.0.0-20220611021443-a3af701111be/go.mod h1:FWqHpmEj39kZYjkb4y+GkFRwJofD3lP2k8ataoNlo2Y= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= -go.starlark.net v0.0.0-20230912135651-745481cf39ed h1:kNt8RXSIU6IRBO9MP3m+6q3WpyBHQQXqSktcyVKDPOQ= -go.starlark.net v0.0.0-20230912135651-745481cf39ed/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= -go.starlark.net v0.0.0-20230921150705-79febcec3f90 h1:XVeSWZcJ+8Bluixg49AIinMVvROaFn+mgmtplhOMGdw= -go.starlark.net v0.0.0-20230921150705-79febcec3f90/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= -go.starlark.net v0.0.0-20230921161717-a9587466d7a5 h1:Hg7PpzzjFq0TBToBkMgmjY0W09rC52nmm+v2ME9ZT5w= -go.starlark.net v0.0.0-20230921161717-a9587466d7a5/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= -go.starlark.net v0.0.0-20230925163745-10651d5192ab h1:7QkXlIVjYdSsKKSGnM0jQdw/2w9W5qcFDGTc00zKqgI= -go.starlark.net v0.0.0-20230925163745-10651d5192ab/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= -go.starlark.net v0.0.0-20231013162135-47c85baa7a64 h1:oEn8uu0f/4jnlInr2y86GrMRux+y9i8XrO8w1jVyVNo= -go.starlark.net v0.0.0-20231013162135-47c85baa7a64/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= -go.starlark.net v0.0.0-20231016134836-22325403fcb3 h1:CKbpFNZNfaNyEWd6C+F1vLZ0WJjukoU45zDErBmRKPs= -go.starlark.net v0.0.0-20231016134836-22325403fcb3/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= -go.starlark.net v0.0.0-20231101134539-556fd59b42f6 h1:+eC0F/k4aBLC4szgOcjd7bDTEnpxADJyWJE0yowgM3E= -go.starlark.net v0.0.0-20231101134539-556fd59b42f6/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= -go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4= -go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= -go.starlark.net v0.0.0-20240307200823-981680b3e495 h1:Ln1SHdenasr/C6gJTSJcxc8L+lFQ+rkA5lwu7ORdWNo= -go.starlark.net v0.0.0-20240307200823-981680b3e495/go.mod h1:MrdO7XaMF3dE3MzuP6mrG0EB3NC7rLWSiEcu9Ii50g8= -go.starlark.net v0.0.0-20240314022150-ee8ed142361c h1:roAjH18hZcwI4hHStHbkXjF5b7UUyZ/0SG3hXNN1SjA= -go.starlark.net v0.0.0-20240314022150-ee8ed142361c/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a h1:Oe+v9w90BBIxQZ4U39+axR8KxrBbxqnRudPPcBIlP3o= go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -548,70 +357,21 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= -golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= -golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= -golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= -golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= -golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -621,35 +381,13 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -657,55 +395,17 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= -golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -714,228 +414,71 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -944,12 +487,9 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -959,7 +499,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -975,12 +514,4 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/runtime/applet.go b/runtime/applet.go index f65d6b39ff..fc8d731cea 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -5,8 +5,9 @@ import ( "crypto/md5" "encoding/json" "fmt" + "strings" + "testing" - "github.com/pkg/errors" starlibgzip "github.com/qri-io/starlib/compress/gzip" starlibbase64 "github.com/qri-io/starlib/encoding/base64" starlibcsv "github.com/qri-io/starlib/encoding/csv" @@ -17,10 +18,10 @@ import ( starlibjson "go.starlark.net/lib/json" starlibmath "go.starlark.net/lib/math" starlibtime "go.starlark.net/lib/time" - "go.starlark.net/resolve" "go.starlark.net/starlark" "go.starlark.net/starlarkstruct" "go.starlark.net/starlarktest" + "go.starlark.net/syntax" "tidbyt.dev/pixlet/render" "tidbyt.dev/pixlet/runtime/modules/animation_runtime" @@ -38,138 +39,163 @@ import ( type ModuleLoader func(*starlark.Thread, string) (starlark.StringDict, error) +type PrintFunc func(thread *starlark.Thread, msg string) + +type AppletOption func(*Applet) error + // ThreadInitializer is called when building a Starlark thread to run an applet // on. It can customize the thread by overriding behavior or attaching thread // local data. type ThreadInitializer func(thread *starlark.Thread) *starlark.Thread -func init() { - resolve.AllowFloat = true - resolve.AllowLambda = true - resolve.AllowNestedDef = true - resolve.AllowSet = true - resolve.AllowRecursion = true -} - type Applet struct { - Filename string - ThreadID string - AppID string - Globals starlark.StringDict - SecretDecryptionKey *SecretDecryptionKey + ID string - src []byte - loader ModuleLoader - predeclared starlark.StringDict - main *starlark.Function + src []byte + loader ModuleLoader + initializers []ThreadInitializer + + globals starlark.StringDict + main *starlark.Function schema *schema.Schema schemaJSON []byte - decrypter decrypter } -func (a *Applet) thread(initializers ...ThreadInitializer) *starlark.Thread { - t := &starlark.Thread{ - Name: a.ThreadID, - Load: a.loadModule, - Print: func(thread *starlark.Thread, msg string) { - fmt.Printf("[%s] %s\n", a.Filename, msg) - }, +func WithModuleLoader(loader ModuleLoader) AppletOption { + return func(a *Applet) error { + a.loader = loader + return nil } +} - if a.decrypter != nil { - a.decrypter.attachToThread(t) +func WithThreadInitializer(initializer ThreadInitializer) AppletOption { + return func(a *Applet) error { + a.initializers = append(a.initializers, initializer) + return nil } +} - random.AttachToThread(t) - - for _, init := range initializers { - t = init(t) +func WithSecretDecryptionKey(key *SecretDecryptionKey) AppletOption { + return func(a *Applet) error { + if decrypter, err := key.decrypterForApp(a); err != nil { + return fmt.Errorf("preparing secret key: %w", err) + } else { + a.initializers = append(a.initializers, func(t *starlark.Thread) *starlark.Thread { + decrypter.attachToThread(t) + return t + }) + return nil + } } +} - return t +func WithPrintFunc(print PrintFunc) AppletOption { + return func(a *Applet) error { + a.initializers = append(a.initializers, func(t *starlark.Thread) *starlark.Thread { + t.Print = print + return t + }) + return nil + } } -// Loads an applet. The script filename is used as a descriptor only, -// and the actual code should be passed in src. Optionally also pass -// loader to make additional starlark modules available to the script. -func (a *Applet) Load(appID string, filename string, src []byte, loader ModuleLoader) (err error) { - return a.LoadWithInitializers(appID, filename, src, loader) +func WithPrintDisabled() AppletOption { + return WithPrintFunc(func(thread *starlark.Thread, msg string) {}) } -func (a *Applet) LoadWithInitializers(appID string, filename string, src []byte, loader ModuleLoader, initializers ...ThreadInitializer) (err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("panic while executing %s: %v", a.Filename, r) - } - }() +func NewApplet(id string, src []byte, opts ...AppletOption) (*Applet, error) { + a := &Applet{ + ID: id, + src: src, + } - a.AppID = appID - a.Filename = filename - a.loader = loader + for _, opt := range opts { + if err := opt(a); err != nil { + return nil, err + } + } - a.src = src + if err := a.load(); err != nil { + return nil, err + } - a.ThreadID = fmt.Sprintf("%s/%x", filename, md5.Sum(src)) + return a, nil +} - if a.SecretDecryptionKey != nil { - a.decrypter, err = a.SecretDecryptionKey.decrypterForApp(a) - if err != nil { - return errors.Wrapf(err, "preparing secret key for %s", a.Filename) +func (a *Applet) load() (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("panic while executing %s: %v", a.ID, r) } - } + }() - a.predeclared = starlark.StringDict{ + predeclared := starlark.StringDict{ "struct": starlark.NewBuiltin("struct", starlarkstruct.Make), } - globals, err := starlark.ExecFile(a.thread(initializers...), a.Filename, a.src, a.predeclared) + globals, err := starlark.ExecFileOptions( + &syntax.FileOptions{ + Set: true, + Recursion: true, + }, + a.newThread(context.Background()), + a.ID, + a.src, + predeclared, + ) if err != nil { return fmt.Errorf("starlark.ExecFile: %v", err) } - a.Globals = globals + a.globals = globals mainFun, found := globals["main"] if !found { - return fmt.Errorf("%s didn't export a main() function", filename) + return fmt.Errorf("%s didn't export a main() function", a.ID) } main, ok := mainFun.(*starlark.Function) if !ok { - return fmt.Errorf("%s exported a main() that is not function", filename) + return fmt.Errorf("%s exported a main() that is not function", a.ID) } a.main = main - schemaFun, _ := a.Globals[schema.SchemaFunctionName].(*starlark.Function) + schemaFun, _ := a.globals[schema.SchemaFunctionName].(*starlark.Function) if schemaFun != nil { - schemaVal, err := a.Call(schemaFun, nil) + schemaVal, err := a.Call(context.Background(), schemaFun) if err != nil { - return errors.Wrapf(err, "calling schema function for %s", a.Filename) + return fmt.Errorf("calling schema function for %s: %w", a.ID, err) } - a.schema, err = schema.FromStarlark(schemaVal, a.Globals) + a.schema, err = schema.FromStarlark(schemaVal, a.globals) if err != nil { - return errors.Wrapf(err, "parsing schema for %s", a.Filename) + return fmt.Errorf("parsing schema for %s: %w", a.ID, err) } a.schemaJSON, err = json.Marshal(a.schema) if err != nil { - return errors.Wrapf(err, "serializing schema to JSON for %s", a.Filename) + return fmt.Errorf("serializing schema to JSON for %s: %w", a.ID, err) } } return nil } -// Runs the applet's main function, passing it configuration as a -// starlark dict. -func (a *Applet) Run(config map[string]string, initializers ...ThreadInitializer) (roots []render.Root, err error) { +// Run executes the applet's main function. It returns the render roots that are +// returned by the applet. +func (a *Applet) Run(ctx context.Context) (roots []render.Root, err error) { + return a.RunWithConfig(ctx, nil) +} + +// RunWithConfig exceutes the applet's main function, passing it configuration as a +// starlark dict. It returns the render roots that are returned by the applet. +func (a *Applet) RunWithConfig(ctx context.Context, config map[string]string) (roots []render.Root, err error) { var args starlark.Tuple if a.main.NumParams() > 0 { starlarkConfig := AppletConfig(config) args = starlark.Tuple{starlarkConfig} } - returnValue, err := a.Call(a.main, args, initializers...) + returnValue, err := a.Call(ctx, a.main, args...) if err != nil { return nil, err } @@ -210,9 +236,9 @@ func (app *Applet) CallSchemaHandler(ctx context.Context, handlerName, parameter } resultVal, err := app.Call( + ctx, handler.Function, - starlark.Tuple{starlark.String(parameter)}, - attachContext(ctx), + starlark.String(parameter), ) if err != nil { return "", fmt.Errorf("calling schema handler %s: %v", handlerName, err) @@ -227,14 +253,14 @@ func (app *Applet) CallSchemaHandler(ctx context.Context, handlerName, parameter return options, nil case schema.ReturnSchema: - sch, err := schema.FromStarlark(resultVal, app.Globals) + sch, err := schema.FromStarlark(resultVal, app.globals) if err != nil { return "", err } s, err := json.Marshal(sch) if err != nil { - return "", errors.Wrap(err, "serializing schema to JSON") + return "", fmt.Errorf("serializing schema to JSON: %w", err) } return string(s), nil @@ -258,33 +284,49 @@ func (app *Applet) GetSchema() string { return string(app.schemaJSON) } -func attachContext(ctx context.Context) ThreadInitializer { - return func(thread *starlark.Thread) *starlark.Thread { - starlarkutil.AttachThreadContext(ctx, thread) +// RunTests runs all test functions that are defined in the applet source. +func (app *Applet) RunTests(t *testing.T) { + app.initializers = append(app.initializers, func(thread *starlark.Thread) *starlark.Thread { + starlarktest.SetReporter(thread, t) return thread + }) + + for name, global := range app.globals { + if !strings.HasPrefix(name, "test_") { + continue + } + + fun, ok := global.(*starlark.Function) + if ok && fun != app.main { + t.Run(name, func(t *testing.T) { + if _, err := app.Call(context.Background(), fun); err != nil { + t.Error(err) + } + }) + } } } // Calls any callable from Applet.Globals. Pass args and receive a // starlark Value, or an error if you're unlucky. -func (a *Applet) Call(callable *starlark.Function, args starlark.Tuple, initializers ...ThreadInitializer) (val starlark.Value, err error) { +func (a *Applet) Call(ctx context.Context, callable *starlark.Function, args ...starlark.Value) (val starlark.Value, err error) { defer func() { if r := recover(); r != nil { - err = fmt.Errorf("panic while running %s: %v", a.Filename, r) + err = fmt.Errorf("panic while running %s: %v", a.ID, r) } }() - t := a.thread(initializers...) + t := a.newThread(ctx) - context.AfterFunc(starlarkutil.ThreadContext(t), func() { - t.Cancel(context.Cause(starlarkutil.ThreadContext(t)).Error()) + context.AfterFunc(ctx, func() { + t.Cancel(context.Cause(ctx).Error()) }) resultVal, err := starlark.Call(t, callable, args, nil) if err != nil { evalErr, ok := err.(*starlark.EvalError) if ok { - return nil, errors.New(evalErr.Backtrace()) + return nil, fmt.Errorf(evalErr.Backtrace()) } return nil, fmt.Errorf( "in %s at %s: %s", @@ -397,3 +439,22 @@ func (a *Applet) loadModule(thread *starlark.Thread, module string) (starlark.St return nil, fmt.Errorf("invalid module: %s", module) } } + +func (a *Applet) newThread(ctx context.Context) *starlark.Thread { + t := &starlark.Thread{ + Name: fmt.Sprintf("%s/%x", a.ID, md5.Sum(a.src)), + Load: a.loadModule, + Print: func(thread *starlark.Thread, msg string) { + fmt.Printf("[%s] %s\n", a.ID, msg) + }, + } + + starlarkutil.AttachThreadContext(ctx, t) + random.AttachToThread(t) + + for _, init := range a.initializers { + t = init(t) + } + + return t +} diff --git a/runtime/applet_test.go b/runtime/applet_test.go index 261a53c4c3..7997d03331 100644 --- a/runtime/applet_test.go +++ b/runtime/applet_test.go @@ -3,6 +3,7 @@ package runtime import ( "archive/zip" "bytes" + "context" "fmt" "testing" @@ -13,15 +14,13 @@ import ( ) func TestLoadEmptySrc(t *testing.T) { - app := &Applet{} - err := app.Load("testid", "test.star", []byte{}, nil) + _, err := NewApplet("test.star", []byte{}) assert.Error(t, err) } func TestLoadMalformed(t *testing.T) { src := "this is not valid starlark" - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + _, err := NewApplet("test.star", []byte(src)) assert.Error(t, err) } @@ -32,9 +31,9 @@ load("render.star", "render") def main(): return render.Root(child=render.Box()) ` - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) + assert.NotNil(t, app) // As is this src = ` @@ -44,9 +43,9 @@ def main2(): main = main2 ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + app, err = NewApplet("test.star", []byte(src)) assert.NoError(t, err) + assert.NotNil(t, app) // And this (a lambda is a function) src = ` @@ -56,9 +55,9 @@ def main2(): main = lambda: main2() ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + app, err = NewApplet("test.star", []byte(src)) assert.NoError(t, err) + assert.NotNil(t, app) // But not this, because a string is not a function src = ` @@ -68,8 +67,7 @@ def main2(): main = "main2" ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + _, err = NewApplet("test.star", []byte(src)) assert.Error(t, err) // And not this either, because here main is gone @@ -78,10 +76,8 @@ load("render.star", "render") def main2(): return render.Root(child=render.Box()) ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + _, err = NewApplet("test.star", []byte(src)) assert.Error(t, err) - } func TestRunMainReturnsFrames(t *testing.T) { @@ -91,10 +87,10 @@ load("render.star", "render") def main(): return [render.Box()] ` - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + assert.NotNil(t, app) + screens, err := app.Run(context.Background()) assert.Error(t, err) assert.Nil(t, screens) @@ -105,10 +101,10 @@ def main(): return render.Root(child=render.Box()) ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + app, err = NewApplet("test.star", []byte(src)) assert.NoError(t, err) - screens, err = app.Run(map[string]string{}) + assert.NotNil(t, app) + screens, err = app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) @@ -118,10 +114,10 @@ load("render.star", "render") def main(): return [render.Root(child=render.Box()), render.Root(child=render.Text("hi"))] ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + app, err = NewApplet("test.star", []byte(src)) assert.NoError(t, err) - screens, err = app.Run(map[string]string{}) + assert.NotNil(t, app) + screens, err = app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } @@ -140,10 +136,10 @@ load("render.star", "render") def main(): return render.Root(child=render.Box()) ` - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - roots, err := app.Run(config) + assert.NotNil(t, app) + roots, err := app.RunWithConfig(context.Background(), config) assert.NoError(t, err) assert.Equal(t, 1, len(roots)) @@ -169,10 +165,10 @@ def main(config): return [render.Root(child=render.Box()) for _ in range(int(config["one"]) + int(config["two"]))] ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) + app, err = NewApplet("test.star", []byte(src)) require.NoError(t, err) - roots, err = app.Run(config) + require.NotNil(t, app) + roots, err = app.RunWithConfig(context.Background(), config) require.NoError(t, err) assert.Equal(t, 3, len(roots)) } @@ -207,10 +203,10 @@ def main(): fail("time broken") return render.Root(child=render.Box()) ` - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - roots, err := app.Run(map[string]string{}) + assert.NotNil(t, app) + roots, err := app.Run(context.Background()) assert.NoError(t, err) assert.Equal(t, 1, len(roots)) @@ -229,10 +225,9 @@ def main(): fail("something went wrong") return render.Root(child=render.Box()) ` - app = &Applet{} - err = app.Load("testid", "test.star", []byte(src), loader) + app, err = NewApplet("test.star", []byte(src), WithModuleLoader(loader)) assert.NoError(t, err) - roots, err = app.Run(map[string]string{}) + roots, err = app.Run(context.Background()) assert.NoError(t, err) assert.Equal(t, 1, len(roots)) @@ -254,10 +249,10 @@ def main(): return thread } - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src), WithThreadInitializer(initializer)) assert.NoError(t, err) - _, err = app.Run(map[string]string{}, initializer) + assert.NotNil(t, app) + _, err = app.Run(context.Background()) assert.NoError(t, err) // our print function should have been called @@ -274,14 +269,14 @@ def main(): return render.Root(child=render.Box()) ` - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - _, err = app.Run(map[string]string{}) + assert.NotNil(t, app) + _, err = app.Run(context.Background()) assert.NoError(t, err) } -func TestZipModule(t *testing.T) { +func TestZIPModule(t *testing.T) { // Create a new zip file to read from starlark // https://go.dev/src/archive/zip/example_test.go buf := new(bytes.Buffer) @@ -302,16 +297,6 @@ func TestZipModule(t *testing.T) { err := w.Close() assert.NoError(t, err) - // override the print function of the thread so we can check we got correct - // values from the zip module. - var printedText []string - initializer := func(thread *starlark.Thread) *starlark.Thread { - thread.Print = func(thread *starlark.Thread, msg string) { - printedText = append(printedText, msg) - } - return thread - } - src := ` load("compress/zipfile.star", "zipfile") def main(config): @@ -322,9 +307,20 @@ def main(config): return [] ` - app := &Applet{} - err = app.Load("testid", "test.star", []byte(src), nil) - _, err = app.Run(map[string]string{"ZIP_BYTES": buf.String()}, initializer) + // override the print function of the thread so we can check we got correct + // values from the zip module. + var printedText []string + printFunc := func(thread *starlark.Thread, msg string) { + printedText = append(printedText, msg) + } + + app, err := NewApplet("test.star", []byte(src), WithPrintFunc(printFunc)) + require.NoError(t, err) + require.NotNil(t, app) + _, err = app.RunWithConfig( + context.Background(), + map[string]string{"ZIP_BYTES": buf.String()}, + ) assert.NoError(t, err) assert.Equal(t, []string{ diff --git a/runtime/cache_test.go b/runtime/cache_test.go index f3d039a6b5..c4a272ecf8 100644 --- a/runtime/cache_test.go +++ b/runtime/cache_test.go @@ -1,6 +1,7 @@ package runtime import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -32,10 +33,10 @@ def main(): return [render.Root(child=render.Box()) for i in range(int(one) + int(two) + int(three))] ` InitCache(NewInMemoryCache()) - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - roots, err := app.Run(map[string]string{}) + assert.NotNil(t, app) + roots, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, roots) assert.Equal(t, 1+2+3, len(roots)) @@ -53,35 +54,35 @@ def main(): return frames ` InitCache(NewInMemoryCache()) - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) + assert.NotNil(t, app) // first time, i == 1 - roots, err := app.Run(map[string]string{}) + roots, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, roots) assert.Equal(t, 1, len(roots)) // i == 2 - roots, err = app.Run(map[string]string{}) + roots, err = app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, roots) assert.Equal(t, 2, len(roots)) // but run the same code using different filename, and cached // data ends up in a different namespace - app = &Applet{} - err = app.Load("testid", "test2.star", []byte(src), nil) + app, err = NewApplet("test2.star", []byte(src)) assert.NoError(t, err) + assert.NotNil(t, app) - roots, _ = app.Run(map[string]string{}) + roots, _ = app.Run(context.Background()) assert.Equal(t, 1, len(roots)) - roots, _ = app.Run(map[string]string{}) + roots, _ = app.Run(context.Background()) assert.Equal(t, 2, len(roots)) - roots, _ = app.Run(map[string]string{}) + roots, _ = app.Run(context.Background()) assert.Equal(t, 3, len(roots)) } @@ -102,10 +103,10 @@ def main(): return render.Root(child=render.Box()) ` InitCache(nil) - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + assert.NotNil(t, app) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } @@ -120,10 +121,10 @@ def main(): return render.Root(child=render.Box()) ` InitCache(nil) - app := &Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + assert.NotNil(t, app) + screens, err := app.Run(context.Background()) assert.Error(t, err) assert.Nil(t, screens) } diff --git a/runtime/httpcache.go b/runtime/httpcache.go index 1eb1d7886d..6c77cef996 100644 --- a/runtime/httpcache.go +++ b/runtime/httpcache.go @@ -14,7 +14,6 @@ import ( "strings" "time" - "github.com/pkg/errors" "tidbyt.dev/pixlet/runtime/modules/starlarkhttp" ) @@ -109,7 +108,7 @@ func (c *cacheClient) RoundTrip(req *http.Request) (*http.Response, error) { func cacheKey(req *http.Request) (string, error) { r, err := httputil.DumpRequest(req, true) if err != nil { - return "", errors.Wrap(err, "failed to serialize request") + return "", fmt.Errorf("%s: %w", "failed to serialize request", err) } h := sha256.Sum256(r) diff --git a/runtime/httpcache_test.go b/runtime/httpcache_test.go index 1f1bb76abb..d4940078a4 100644 --- a/runtime/httpcache_test.go +++ b/runtime/httpcache_test.go @@ -1,6 +1,7 @@ package runtime import ( + "context" "fmt" "math/rand" "net/http" @@ -18,11 +19,11 @@ func TestInitHTTP(t *testing.T) { b, err := os.ReadFile("testdata/httpcache.star") assert.NoError(t, err) - app := &Applet{} - err = app.Load("httpid", "httpcache.star", b, nil) + app, err := NewApplet("httpcache.star", b) assert.NoError(t, err) + assert.NotNil(t, app) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/modules/hmac/hmac_test.go b/runtime/modules/hmac/hmac_test.go index c193db6dd4..6ac6efdd29 100644 --- a/runtime/modules/hmac/hmac_test.go +++ b/runtime/modules/hmac/hmac_test.go @@ -1,6 +1,7 @@ package hmac_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -25,11 +26,11 @@ def main(): ` func TestHmac(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("hmacid", "hmac_test.star", []byte(hmacSource), nil) + app, err := runtime.NewApplet("hmac_test.star", []byte(hmacSource)) assert.NoError(t, err) + assert.NotNil(t, app) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/modules/humanize/humanize_test.go b/runtime/modules/humanize/humanize_test.go index e79c1c18f0..95a3c84cd8 100644 --- a/runtime/modules/humanize/humanize_test.go +++ b/runtime/modules/humanize/humanize_test.go @@ -1,6 +1,7 @@ package humanize_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -79,11 +80,11 @@ def main(): ` func TestHumanize(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("humanid", "human.star", []byte(humanSource), nil) + app, err := runtime.NewApplet("human.star", []byte(humanSource)) assert.NoError(t, err) + assert.NotNil(t, app) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/modules/qrcode/qrcode_test.go b/runtime/modules/qrcode/qrcode_test.go index cf928d4c18..fb5144ca97 100644 --- a/runtime/modules/qrcode/qrcode_test.go +++ b/runtime/modules/qrcode/qrcode_test.go @@ -1,6 +1,7 @@ package qrcode_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -28,11 +29,10 @@ def main(): ` func TestQRCode(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("testid", "test.star", []byte(qrCodeSource), nil) + app, err := runtime.NewApplet("test.star", []byte(qrCodeSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/modules/random/random.go b/runtime/modules/random/random.go index 24e124ba08..b5b2565bf5 100644 --- a/runtime/modules/random/random.go +++ b/runtime/modules/random/random.go @@ -38,7 +38,6 @@ func AttachToThread(t *starlark.Thread) { func LoadModule() (starlark.StringDict, error) { once.Do(func() { - rand.Seed(time.Now().UnixNano()) module = starlark.StringDict{ ModuleName: &starlarkstruct.Module{ Name: ModuleName, diff --git a/runtime/modules/random/random_test.go b/runtime/modules/random/random_test.go index 6120f59ab8..683ecb4e25 100644 --- a/runtime/modules/random/random_test.go +++ b/runtime/modules/random/random_test.go @@ -1,6 +1,7 @@ package random_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -47,11 +48,10 @@ def main(): ` func TestRandom(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("randomid", "random_test.star", []byte(randomSrc), nil) + app, err := runtime.NewApplet("random_test.star", []byte(randomSrc)) require.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) require.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/modules/starlarkhttp/testdata/test.star b/runtime/modules/starlarkhttp/testdata/test.star index da38e77d4b..bef3b5c4ce 100644 --- a/runtime/modules/starlarkhttp/testdata/test.star +++ b/runtime/modules/starlarkhttp/testdata/test.star @@ -1,5 +1,5 @@ -load("http.star", "http") load("assert.star", "assert") +load("http.star", "http") res_1 = http.get(test_server_url, params = {"a": "b", "c": "d"}) assert.eq(res_1.url, test_server_url + "?a=b&c=d") diff --git a/runtime/modules/sunrise/sunrise_test.go b/runtime/modules/sunrise/sunrise_test.go index d8ff3e88cd..247b3ff372 100644 --- a/runtime/modules/sunrise/sunrise_test.go +++ b/runtime/modules/sunrise/sunrise_test.go @@ -1,6 +1,7 @@ package sunrise_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -51,11 +52,10 @@ def main(): ` func TestSunrise(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("sunid", "sun.star", []byte(sunSource), nil) + app, err := runtime.NewApplet("sun.star", []byte(sunSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/modules/xpath/xpath_test.go b/runtime/modules/xpath/xpath_test.go index 54fde86b92..25d8fc7168 100644 --- a/runtime/modules/xpath/xpath_test.go +++ b/runtime/modules/xpath/xpath_test.go @@ -1,6 +1,7 @@ package xpath_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -73,10 +74,9 @@ def main(): return [r.Root(child=r.Text("1337"))] ` - app := &runtime.Applet{} - err := app.Load("testid", "test.star", []byte(src), nil) + app, err := runtime.NewApplet("test.star", []byte(src)) require.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) require.NoError(t, err) assert.NotNil(t, screens) } diff --git a/runtime/render_test.go b/runtime/render_test.go index e7cbe18ffd..961c58b3dd 100644 --- a/runtime/render_test.go +++ b/runtime/render_test.go @@ -2,6 +2,7 @@ package runtime import ( "bytes" + "context" "encoding/base64" "fmt" "image" @@ -135,10 +136,9 @@ def main(): ` func TestBigDotStar(t *testing.T) { - app := &Applet{} - err := app.Load("bigid", "big.star", []byte(TestDotStar), nil) + app, err := NewApplet("big.star", []byte(TestDotStar)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } @@ -158,11 +158,10 @@ def main(): ` ) - app := &Applet{} - err := app.Load("boxid", filename, []byte(src), nil) + app, err := NewApplet(filename, []byte(src)) assert.NoError(t, err) - b := app.Globals["b"] + b := app.globals["b"] assert.IsType(t, &render_runtime.Box{}, b) widget := b.(*render_runtime.Box).AsRenderWidget() @@ -194,11 +193,10 @@ def main(): ` ) - app := &Applet{} - err := app.Load("textid", filename, []byte(src), nil) + app, err := NewApplet(filename, []byte(src)) assert.NoError(t, err) - txt := app.Globals["t"] + txt := app.globals["t"] assert.IsType(t, &render_runtime.Text{}, txt) widget := txt.(*render_runtime.Text).AsRenderWidget() @@ -239,11 +237,10 @@ def main(): `, base64.StdEncoding.EncodeToString(p.Bytes())) - app := &Applet{} - err := app.Load("imageid", filename, []byte(src), nil) + app, err := NewApplet(filename, []byte(src)) assert.NoError(t, err) - starlarkP := app.Globals["img"] + starlarkP := app.globals["img"] require.IsType(t, &render_runtime.Image{}, starlarkP) actualIm := render.PaintWidget(starlarkP.(*render_runtime.Image).AsRenderWidget(), image.Rect(0, 0, 64, 32), 0) diff --git a/runtime/secret.go b/runtime/secret.go index f94106006a..e32799d4e9 100644 --- a/runtime/secret.go +++ b/runtime/secret.go @@ -10,7 +10,6 @@ import ( "github.com/google/tink/go/hybrid" "github.com/google/tink/go/keyset" "github.com/google/tink/go/tink" - "github.com/pkg/errors" "go.starlark.net/starlark" "go.starlark.net/starlarkstruct" ) @@ -42,18 +41,18 @@ func (sek *SecretEncryptionKey) Encrypt(appID, plaintext string) (string, error) r := bytes.NewReader(sek.PublicKeysetJSON) kh, err := keyset.ReadWithNoSecrets(keyset.NewJSONReader(r)) if err != nil { - return "", errors.Wrap(err, "reading keyset JSON") + return "", fmt.Errorf("%s: %w", "reading keyset JSON", err) } enc, err := hybrid.NewHybridEncrypt(kh) if err != nil { - return "", errors.Wrap(err, "NewHybridEncrypt") + return "", fmt.Errorf("%s: %w", "NewHybridEncrypt", err) } context := []byte(appID) ciphertext, err := enc.Encrypt([]byte(plaintext), context) if err != nil { - return "", errors.Wrap(err, "encrypting secret") + return "", fmt.Errorf("%s: %w", "encrypting secret", err) } return base64.StdEncoding.EncodeToString(ciphertext), nil @@ -85,21 +84,21 @@ func (sdk *SecretDecryptionKey) decrypterForApp(a *Applet) (decrypter, error) { r := bytes.NewReader(sdk.EncryptedKeysetJSON) kh, err := keyset.Read(keyset.NewJSONReader(r), sdk.KeyEncryptionKey) if err != nil { - return nil, errors.Wrap(err, "reading keyset JSON") + return nil, fmt.Errorf("%s: %w", "reading keyset JSON", err) } dec, err := hybrid.NewHybridDecrypt(kh) if err != nil { - return nil, errors.Wrap(err, "NewHybridDecrypt") + return nil, fmt.Errorf("%s: %w", "NewHybridDecrypt", err) } - context := []byte(a.AppID) + context := []byte(a.ID) return func(s starlark.String) (starlark.String, error) { v := regexp.MustCompile(`\s`).ReplaceAllString(s.GoString(), "") ciphertext, err := base64.StdEncoding.DecodeString(v) if err != nil { - return "", errors.Wrapf(err, "base64 decoding of secret: %s", s) + return "", fmt.Errorf("base64 decoding of secret: %s: %w", s, err) } cleartext, err := dec.Decrypt(ciphertext, context) diff --git a/runtime/secret_test.go b/runtime/secret_test.go index a5a84f64ac..a5749197b1 100644 --- a/runtime/secret_test.go +++ b/runtime/secret_test.go @@ -2,6 +2,7 @@ package runtime import ( "bytes" + "context" "fmt" "testing" @@ -71,14 +72,10 @@ def main(): return render.Root(child=render.Box()) `, plaintext, encrypted) - app := &Applet{ - SecretDecryptionKey: decryptionKey, - } - - err = app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("testid", []byte(src), WithSecretDecryptionKey(decryptionKey)) require.NoError(t, err) - roots, err := app.Run(nil) + roots, err := app.Run(context.Background()) assert.NoError(t, err) assert.Equal(t, 1, len(roots)) } @@ -128,14 +125,10 @@ def main(): return render.Root(child=render.Box()) `, plaintext, encrypted) - app := &Applet{ - SecretDecryptionKey: nil, - } - - err = app.Load("testid", "test.star", []byte(src), nil) + app, err := NewApplet("test.star", []byte(src)) require.NoError(t, err) - roots, err := app.Run(nil) + roots, err := app.Run(context.Background()) assert.NoError(t, err) assert.Equal(t, 1, len(roots)) } diff --git a/runtime/test.star b/runtime/test.star index 72e8f1cce4..b51df76a2c 100644 --- a/runtime/test.star +++ b/runtime/test.star @@ -1,6 +1,6 @@ -load("render.star", "render") load("assert.star", "assert") load("encoding/base64.star", "base64") +load("render.star", "render") # Font tests assert.eq(render.fonts["6x13"], "6x13") diff --git a/runtime/testdata/httpcache.star b/runtime/testdata/httpcache.star index 9805e6be63..0a1cbe18a5 100644 --- a/runtime/testdata/httpcache.star +++ b/runtime/testdata/httpcache.star @@ -5,9 +5,9 @@ Description: It's an app for testing. Author: Test Dev """ -load("render.star", "render") -load("http.star", "http") load("assert.star", "assert") +load("http.star", "http") +load("render.star", "render") def main(config): resp = http.get( diff --git a/schema/color_test.go b/schema/color_test.go index 5cecd4ca32..8a082af24f 100644 --- a/schema/color_test.go +++ b/schema/color_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -55,11 +56,10 @@ assert(s2.palette[3] == "#323334") def main(): return [] ` - app := &runtime.Applet{} - err := app.Load("cid", "colors.star", []byte(src), nil) + app, err := runtime.NewApplet("colors.star", []byte(src)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } @@ -90,48 +90,47 @@ def main(config): return [] ` - app := &runtime.Applet{} - err := app.Load("cid", "colors.star", []byte(src), nil) + app, err := runtime.NewApplet("colors.star", []byte(src)) assert.NoError(t, err) // Well formed input -> success - screens, err := app.Run(map[string]string{"default": "#ffaa77", "palette": "[]"}) + screens, err := app.RunWithConfig(context.Background(), map[string]string{"default": "#ffaa77", "palette": "[]"}) assert.NoError(t, err) assert.NotNil(t, screens) // Bad default - _, err = app.Run(map[string]string{"default": "#nothex", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#nothex", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "0", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "0", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "01", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "01", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#01", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#01", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "0123", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "0123", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#0123", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#0123", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "01234", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "01234", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#01234", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#01234", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "0123456", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "0123456", "palette": "[]"}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#0123456", "palette": "[]"}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#0123456", "palette": "[]"}) assert.Error(t, err) // Bad palette - _, err = app.Run(map[string]string{"default": "#ffaa77", "palette": `["nothex"]`}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#ffaa77", "palette": `["nothex"]`}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "0"]`}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "0"]`}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "#0f"]`}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "#0f"]`}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "0123"]`}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "0123"]`}) assert.Error(t, err) - _, err = app.Run(map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "0123456"]`}) + _, err = app.RunWithConfig(context.Background(), map[string]string{"default": "#ffaa77", "palette": `["fff", "ffaabb", "0123456"]`}) assert.Error(t, err) } diff --git a/schema/datetime_test.go b/schema/datetime_test.go index 8189f85834..eae976bec8 100644 --- a/schema/datetime_test.go +++ b/schema/datetime_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -31,11 +32,10 @@ def main(): ` func TestDateTime(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("dtid", "date_time.star", []byte(dateTimeSource), nil) + app, err := runtime.NewApplet("date_time.star", []byte(dateTimeSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/dropdown_test.go b/schema/dropdown_test.go index 08426778d4..5f6d4b708a 100644 --- a/schema/dropdown_test.go +++ b/schema/dropdown_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -51,11 +52,10 @@ def main(): ` func TestDropdown(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("ddid", "dropdown.star", []byte(dropdownSource), nil) + app, err := runtime.NewApplet("dropdown.star", []byte(dropdownSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/generated_test.go b/schema/generated_test.go index 03180d91c1..bf3369a329 100644 --- a/schema/generated_test.go +++ b/schema/generated_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -29,11 +30,10 @@ def main(): ` func TestGenerated(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("gid", "generated.star", []byte(generatedSource), nil) + app, err := runtime.NewApplet("generated.star", []byte(generatedSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/handler_test.go b/schema/handler_test.go index 07aabc4a8c..7749055876 100644 --- a/schema/handler_test.go +++ b/schema/handler_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -30,19 +31,17 @@ def main(): ` func TestHandler(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("hid", "handler.star", []byte(handlerSource), nil) + app, err := runtime.NewApplet("handler.star", []byte(handlerSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } func TestHandlerBadParams(t *testing.T) { // Handler is a string - app := &runtime.Applet{} - err := app.Load("tid", "text.star", []byte(` + app, err := runtime.NewApplet("text.star", []byte(` load("schema.star", "schema") def foobar(param): @@ -55,12 +54,12 @@ h = schema.Handler( def main(): return [] -`), nil) +`)) assert.Error(t, err) + assert.Nil(t, app) // Type is not valid - app = &runtime.Applet{} - err = app.Load("tid", "text.star", []byte(` + app, err = runtime.NewApplet("text.star", []byte(` load("schema.star", "schema") def foobar(param): @@ -73,7 +72,7 @@ h = schema.Handler( def main(): return [] -`), nil) +`)) assert.Error(t, err) - + assert.Nil(t, app) } diff --git a/schema/location_test.go b/schema/location_test.go index fde878d1d4..97ee940e31 100644 --- a/schema/location_test.go +++ b/schema/location_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -31,11 +32,10 @@ def main(): ` func TestLocation(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("lid", "location.star", []byte(locationSource), nil) + app, err := runtime.NewApplet("location.star", []byte(locationSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/locationbased_test.go b/schema/locationbased_test.go index 399538da31..a79468181d 100644 --- a/schema/locationbased_test.go +++ b/schema/locationbased_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -61,11 +62,10 @@ def main(): ` func TestLocationBased(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("lbid", "location_based.star", []byte(locationBasedSource), nil) + app, err := runtime.NewApplet("location_based.star", []byte(locationBasedSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/module_test.go b/schema/module_test.go index 0d4aa8a773..539ea6e59a 100644 --- a/schema/module_test.go +++ b/schema/module_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -41,20 +42,18 @@ def main(): ` func TestStarlarkSchema(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("starlarkid", "starlark.star", []byte(schemaSource), nil) + app, err := runtime.NewApplet("starlark.star", []byte(schemaSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } func TestSchemaModuleLoads(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("sourceid", "source.star", []byte(moduleSource), nil) + app, err := runtime.NewApplet("source.star", []byte(moduleSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/oauth2_test.go b/schema/oauth2_test.go index 4613f4f368..35adcc430a 100644 --- a/schema/oauth2_test.go +++ b/schema/oauth2_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -47,11 +48,10 @@ def main(): ` func TestOAuth2(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("oaid", "oauth2.star", []byte(oauth2Source), nil) + app, err := runtime.NewApplet("oauth2.star", []byte(oauth2Source)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/option_test.go b/schema/option_test.go index aa0216d49a..5eb7f6efa2 100644 --- a/schema/option_test.go +++ b/schema/option_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -27,11 +28,10 @@ def main(): ` func TestOption(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("oid", "option.star", []byte(optionSource), nil) + app, err := runtime.NewApplet("option.star", []byte(optionSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/photoselect_test.go b/schema/photoselect_test.go index 2d9dd1ae4a..c35c9cfa17 100644 --- a/schema/photoselect_test.go +++ b/schema/photoselect_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -31,11 +32,10 @@ def main(): ` func TestPhotoSelect(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("photid", "photo_select.star", []byte(photoSelectSource), nil) + app, err := runtime.NewApplet("photo_select.star", []byte(photoSelectSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/schema_test.go b/schema/schema_test.go index 20753be38d..a356e6cc7f 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -5,7 +5,6 @@ import ( "encoding/json" "testing" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tidbyt.dev/pixlet/runtime" @@ -13,13 +12,7 @@ import ( ) func loadApp(code string) (*runtime.Applet, error) { - app := &runtime.Applet{} - err := app.Load("testid", "test.star", []byte(code), nil) - if err != nil { - return nil, errors.WithStack(err) - } - - return app, nil + return runtime.NewApplet("test.star", []byte(code)) } func TestSchemaAllTypesSuccess(t *testing.T) { diff --git a/schema/text_test.go b/schema/text_test.go index 30fa3315ad..86a26b9a32 100644 --- a/schema/text_test.go +++ b/schema/text_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -33,11 +34,10 @@ def main(): ` func TestText(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("tid", "text.star", []byte(textSource), nil) + app, err := runtime.NewApplet("text.star", []byte(textSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/toggle_test.go b/schema/toggle_test.go index 78afb65485..143a6fb46d 100644 --- a/schema/toggle_test.go +++ b/schema/toggle_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -33,11 +34,10 @@ def main(): ` func TestToggle(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("tid", "toggle.star", []byte(toggleSource), nil) + app, err := runtime.NewApplet("toggle.star", []byte(toggleSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/schema/typeahead_test.go b/schema/typeahead_test.go index fc0af0e6c3..e07742eaa2 100644 --- a/schema/typeahead_test.go +++ b/schema/typeahead_test.go @@ -1,6 +1,7 @@ package schema_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -46,11 +47,10 @@ def main(): ` func TestTypeahead(t *testing.T) { - app := &runtime.Applet{} - err := app.Load("tahid", "typeahead.star", []byte(typeaheadSource), nil) + app, err := runtime.NewApplet("typeahead.star", []byte(typeaheadSource)) assert.NoError(t, err) - screens, err := app.Run(map[string]string{}) + screens, err := app.Run(context.Background()) assert.NoError(t, err) assert.NotNil(t, screens) } diff --git a/server/loader/loader.go b/server/loader/loader.go index 2d37cdfd2d..32ae9322b1 100644 --- a/server/loader/loader.go +++ b/server/loader/loader.go @@ -10,12 +10,9 @@ import ( "log" "time" - "go.starlark.net/starlark" - "tidbyt.dev/pixlet/encode" "tidbyt.dev/pixlet/runtime" "tidbyt.dev/pixlet/schema" - "tidbyt.dev/pixlet/starlarkutil" ) // Loader is a structure to provide applet loading when a file changes or on @@ -72,10 +69,12 @@ func NewLoader( runtime.InitCache(cache) if !l.watch { - err := loadScript(&l.applet, "app-id", l.filename) + app, err := loadScript("app-id", l.filename) l.markInitialLoadComplete() if err != nil { return nil, err + } else { + l.applet = *app } } @@ -157,24 +156,22 @@ func (l *Loader) CallSchemaHandler(ctx context.Context, handlerName, parameter s func (l *Loader) loadApplet(config map[string]string) (string, error) { if l.watch { - err := loadScript(&l.applet, "app-id", l.filename) + app, err := loadScript("app-id", l.filename) l.markInitialLoadComplete() if err != nil { return "", err + } else { + l.applet = *app } } - threadInitializer := func(thread *starlark.Thread) *starlark.Thread { - ctx, _ := context.WithTimeoutCause( - context.Background(), - time.Duration(l.timeout)*time.Millisecond, - fmt.Errorf("timeout after %dms", l.timeout), - ) - starlarkutil.AttachThreadContext(ctx, thread) - return thread - } + ctx, _ := context.WithTimeoutCause( + context.Background(), + time.Duration(l.timeout)*time.Millisecond, + fmt.Errorf("timeout after %dms", l.timeout), + ) - roots, err := l.applet.Run(config, threadInitializer) + roots, err := l.applet.RunWithConfig(ctx, config) if err != nil { return "", fmt.Errorf("error running script: %w", err) } diff --git a/server/loader/script.go b/server/loader/script.go index 7874910caf..4a27f3ff97 100644 --- a/server/loader/script.go +++ b/server/loader/script.go @@ -4,21 +4,16 @@ package loader import ( "fmt" - "io/ioutil" + "os" "tidbyt.dev/pixlet/runtime" ) -func loadScript(applet *runtime.Applet, appID string, filename string) error { - src, err := ioutil.ReadFile(filename) +func loadScript(appID string, filename string) (*runtime.Applet, error) { + src, err := os.ReadFile(filename) if err != nil { - return fmt.Errorf("failed to read file %s: %w", filename, err) + return nil, fmt.Errorf("failed to read file %s: %w", filename, err) } - err = applet.Load(appID, filename, src, nil) - if err != nil { - return fmt.Errorf("failed to load applet: %w", err) - } - - return nil + return runtime.NewApplet(appID, src) } diff --git a/server/loader/script_js.go b/server/loader/script_js.go index bca15e3960..c07b9b4fa1 100644 --- a/server/loader/script_js.go +++ b/server/loader/script_js.go @@ -4,28 +4,23 @@ package loader import ( "fmt" - "io/ioutil" + "io" "net/http" "tidbyt.dev/pixlet/runtime" ) -func loadScript(applet *runtime.Applet, appID string, filename string) error { +func loadScript(appID string, filename string) (*runtime.Applet, error) { res, err := http.Get(filename) if err != nil { - return fmt.Errorf("failed to fetch file %s: %w", filename, err) + return nil, fmt.Errorf("failed to fetch file %s: %w", filename, err) } defer res.Body.Close() - src, err := ioutil.ReadAll(res.Body) + src, err := io.ReadAll(res.Body) if err != nil { - return fmt.Errorf("failed to read file %s: %w", filename, err) + return nil, fmt.Errorf("failed to read file %s: %w", filename, err) } - err = applet.Load(appID, filename, src, nil) - if err != nil { - return fmt.Errorf("failed to load applet: %w", err) - } - - return nil + return runtime.NewApplet(appID, src) } From 92dda5e2395cd4cb5e1aaf8001cd7854c5cf88b9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:00:51 +0000 Subject: [PATCH 06/19] fix(deps): update dependency @emotion/styled to v11.11.5 (#1035) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 46 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9e79e316a2..8cd47fe572 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "Apache 2.0", "dependencies": { "@emotion/react": "11.11.4", - "@emotion/styled": "11.11.0", + "@emotion/styled": "11.11.5", "@fontsource/barlow": "4.5.9", "@fontsource/material-icons": "4.5.4", "@fortawesome/fontawesome-svg-core": "6.5.1", @@ -1960,9 +1960,9 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", "dependencies": { "@emotion/memoize": "^0.8.1" } @@ -1996,9 +1996,9 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", - "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", "dependencies": { "@emotion/hash": "^0.9.1", "@emotion/memoize": "^0.8.1", @@ -2013,14 +2013,14 @@ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", "@emotion/utils": "^1.2.1" }, @@ -9998,9 +9998,9 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", "requires": { "@emotion/memoize": "^0.8.1" } @@ -10026,9 +10026,9 @@ } }, "@emotion/serialize": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", - "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", "requires": { "@emotion/hash": "^0.9.1", "@emotion/memoize": "^0.8.1", @@ -10043,14 +10043,14 @@ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", "requires": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", "@emotion/utils": "^1.2.1" } diff --git a/package.json b/package.json index 9b2c445b49..f352a2e312 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ }, "dependencies": { "@emotion/react": "11.11.4", - "@emotion/styled": "11.11.0", + "@emotion/styled": "11.11.5", "@fontsource/barlow": "4.5.9", "@fontsource/material-icons": "4.5.4", "@fortawesome/fontawesome-svg-core": "6.5.1", From 5fbb713a304fcde223c58c61c44f6e11897067b5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:12:58 +0000 Subject: [PATCH 07/19] fix(deps): update github.com/google/pprof digest to 26353dc (#1037) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 317e8c198c..501892a9ce 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/gitsight/go-vcsurl v1.0.1 github.com/go-git/go-git/v5 v5.11.0 github.com/go-playground/validator/v10 v10.15.1 - github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f + github.com/google/pprof v0.0.0-20240416155748-26353dc0451f github.com/google/tink/go v1.7.0 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 diff --git a/go.sum b/go.sum index e9dd98c443..dc1153f630 100644 --- a/go.sum +++ b/go.sum @@ -157,6 +157,8 @@ 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-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY= github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +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/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= From e309cc57a4fc894af61d1c1105a71c5ebceae27e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:11:57 +0000 Subject: [PATCH 08/19] fix(deps): update go.starlark.net digest to 9b43f0a (#1038) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 501892a9ce..ef7399c541 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/tidbyt/go-libwebp v0.0.0-20230922075150-fb11063b2a6a github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/zachomedia/go-bdf v0.0.0-20220611021443-a3af701111be - go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a + go.starlark.net v0.0.0-20240411212711-9b43f0afd521 golang.org/x/image v0.15.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.7.0 diff --git a/go.sum b/go.sum index dc1153f630..195d01f9c5 100644 --- a/go.sum +++ b/go.sum @@ -350,6 +350,8 @@ go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1dr go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a h1:Oe+v9w90BBIxQZ4U39+axR8KxrBbxqnRudPPcBIlP3o= go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= +go.starlark.net v0.0.0-20240411212711-9b43f0afd521 h1:1Ufp2S2fPpj0RHIQ4rbzpCdPLCPkzdK7BaVFH3nkYBQ= +go.starlark.net v0.0.0-20240411212711-9b43f0afd521/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= From a174b0e12c47613e4908c451f5ab35f0f24cf469 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:39:46 +0000 Subject: [PATCH 09/19] fix(deps): update font awesome to v6.5.2 (#1039) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 66 +++++++++++++++++++++++------------------------ package.json | 6 ++--- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8cd47fe572..a4b2928a71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ "@emotion/styled": "11.11.5", "@fontsource/barlow": "4.5.9", "@fontsource/material-icons": "4.5.4", - "@fortawesome/fontawesome-svg-core": "6.5.1", - "@fortawesome/free-brands-svg-icons": "6.5.1", - "@fortawesome/free-solid-svg-icons": "6.5.1", + "@fortawesome/fontawesome-svg-core": "6.5.2", + "@fortawesome/free-brands-svg-icons": "6.5.2", + "@fortawesome/free-solid-svg-icons": "6.5.2", "@fortawesome/react-fontawesome": "0.2.0", "@mui/icons-material": "5.15.14", "@mui/lab": "5.0.0-alpha.169", @@ -2102,45 +2102,45 @@ "integrity": "sha512-YGmXkkEdu6EIgpFKNmB/nIXzZocwSmbI01Ninpmml8x8BT0M6RR++V1KqOfpzZ6Cw/FQ2/KYonQ3x4IY/4VRRA==" }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", - "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", - "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.1" + "@fortawesome/fontawesome-common-types": "6.5.2" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz", - "integrity": "sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz", + "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.1" + "@fortawesome/fontawesome-common-types": "6.5.2" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", - "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.1" + "@fortawesome/fontawesome-common-types": "6.5.2" }, "engines": { "node": ">=6" @@ -10117,32 +10117,32 @@ "integrity": "sha512-YGmXkkEdu6EIgpFKNmB/nIXzZocwSmbI01Ninpmml8x8BT0M6RR++V1KqOfpzZ6Cw/FQ2/KYonQ3x4IY/4VRRA==" }, "@fortawesome/fontawesome-common-types": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", - "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==" + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==" }, "@fortawesome/fontawesome-svg-core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", - "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", "requires": { - "@fortawesome/fontawesome-common-types": "6.5.1" + "@fortawesome/fontawesome-common-types": "6.5.2" } }, "@fortawesome/free-brands-svg-icons": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz", - "integrity": "sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz", + "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==", "requires": { - "@fortawesome/fontawesome-common-types": "6.5.1" + "@fortawesome/fontawesome-common-types": "6.5.2" } }, "@fortawesome/free-solid-svg-icons": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", - "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", "requires": { - "@fortawesome/fontawesome-common-types": "6.5.1" + "@fortawesome/fontawesome-common-types": "6.5.2" } }, "@fortawesome/react-fontawesome": { diff --git a/package.json b/package.json index f352a2e312..be52051750 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,9 @@ "@emotion/styled": "11.11.5", "@fontsource/barlow": "4.5.9", "@fontsource/material-icons": "4.5.4", - "@fortawesome/fontawesome-svg-core": "6.5.1", - "@fortawesome/free-brands-svg-icons": "6.5.1", - "@fortawesome/free-solid-svg-icons": "6.5.1", + "@fortawesome/fontawesome-svg-core": "6.5.2", + "@fortawesome/free-brands-svg-icons": "6.5.2", + "@fortawesome/free-solid-svg-icons": "6.5.2", "@fortawesome/react-fontawesome": "0.2.0", "@mui/icons-material": "5.15.14", "@mui/lab": "5.0.0-alpha.169", From 7865dd96cfb8f939974fe864fa11c70bfc940ff1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 01:22:04 +0000 Subject: [PATCH 10/19] fix(deps): update material-ui monorepo (#1040) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 78 +++++++++++++++++++++++------------------------ package.json | 6 ++-- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4b2928a71..b24947fca6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,9 +17,9 @@ "@fortawesome/free-brands-svg-icons": "6.5.2", "@fortawesome/free-solid-svg-icons": "6.5.2", "@fortawesome/react-fontawesome": "0.2.0", - "@mui/icons-material": "5.15.14", - "@mui/lab": "5.0.0-alpha.169", - "@mui/material": "5.15.14", + "@mui/icons-material": "5.15.15", + "@mui/lab": "5.0.0-alpha.170", + "@mui/material": "5.15.15", "@mui/x-date-pickers": "5.0.20", "@reduxjs/toolkit": "1.9.7", "axios": "1.6.8", @@ -2415,18 +2415,18 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz", - "integrity": "sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.15.tgz", + "integrity": "sha512-aXnw29OWQ6I5A47iuWEI6qSSUfH6G/aCsW9KmW3LiFqr7uXZBK4Ks+z8G+qeIub8k0T5CMqlT2q0L+ZJTMrqpg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.14.tgz", - "integrity": "sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.15.tgz", + "integrity": "sha512-kkeU/pe+hABcYDH6Uqy8RmIsr2S/y5bP2rp+Gat4CcRjCcVne6KudS1NrZQhUCRysrTDCAhcbcf9gt+/+pGO2g==", "dependencies": { "@babel/runtime": "^7.23.9" }, @@ -2449,13 +2449,13 @@ } }, "node_modules/@mui/lab": { - "version": "5.0.0-alpha.169", - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.169.tgz", - "integrity": "sha512-h6xe1K6ISKUbyxTDgdvql4qoDP6+q8ad5fg9nXQxGLUrIeT2jVrBuT/jRECSTufbnhzP+V5kulvYxaMfM8rEdA==", + "version": "5.0.0-alpha.170", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.170.tgz", + "integrity": "sha512-0bDVECGmrNjd3+bLdcLiwYZ0O4HP5j5WSQm5DV6iA/Z9kr8O6AnvZ1bv9ImQbbX7Gj3pX4o43EKwCutj3EQxQg==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/system": "^5.15.14", + "@mui/system": "^5.15.15", "@mui/types": "^7.2.14", "@mui/utils": "^5.15.14", "clsx": "^2.1.0", @@ -2497,14 +2497,14 @@ } }, "node_modules/@mui/material": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz", - "integrity": "sha512-kEbRw6fASdQ1SQ7LVdWR5OlWV3y7Y54ZxkLzd6LV5tmz+NpO3MJKZXSfgR0LHMP7meKsPiMm4AuzV0pXDpk/BQ==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", + "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.14", - "@mui/system": "^5.15.14", + "@mui/core-downloads-tracker": "^5.15.15", + "@mui/system": "^5.15.15", "@mui/types": "^7.2.14", "@mui/utils": "^5.15.14", "@types/react-transition-group": "^4.4.10", @@ -2611,9 +2611,9 @@ } }, "node_modules/@mui/system": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.14.tgz", - "integrity": "sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz", + "integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/private-theming": "^5.15.14", @@ -10320,26 +10320,26 @@ } }, "@mui/core-downloads-tracker": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz", - "integrity": "sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==" + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.15.tgz", + "integrity": "sha512-aXnw29OWQ6I5A47iuWEI6qSSUfH6G/aCsW9KmW3LiFqr7uXZBK4Ks+z8G+qeIub8k0T5CMqlT2q0L+ZJTMrqpg==" }, "@mui/icons-material": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.14.tgz", - "integrity": "sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.15.tgz", + "integrity": "sha512-kkeU/pe+hABcYDH6Uqy8RmIsr2S/y5bP2rp+Gat4CcRjCcVne6KudS1NrZQhUCRysrTDCAhcbcf9gt+/+pGO2g==", "requires": { "@babel/runtime": "^7.23.9" } }, "@mui/lab": { - "version": "5.0.0-alpha.169", - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.169.tgz", - "integrity": "sha512-h6xe1K6ISKUbyxTDgdvql4qoDP6+q8ad5fg9nXQxGLUrIeT2jVrBuT/jRECSTufbnhzP+V5kulvYxaMfM8rEdA==", + "version": "5.0.0-alpha.170", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.170.tgz", + "integrity": "sha512-0bDVECGmrNjd3+bLdcLiwYZ0O4HP5j5WSQm5DV6iA/Z9kr8O6AnvZ1bv9ImQbbX7Gj3pX4o43EKwCutj3EQxQg==", "requires": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/system": "^5.15.14", + "@mui/system": "^5.15.15", "@mui/types": "^7.2.14", "@mui/utils": "^5.15.14", "clsx": "^2.1.0", @@ -10354,14 +10354,14 @@ } }, "@mui/material": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz", - "integrity": "sha512-kEbRw6fASdQ1SQ7LVdWR5OlWV3y7Y54ZxkLzd6LV5tmz+NpO3MJKZXSfgR0LHMP7meKsPiMm4AuzV0pXDpk/BQ==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", + "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", "requires": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.14", - "@mui/system": "^5.15.14", + "@mui/core-downloads-tracker": "^5.15.15", + "@mui/system": "^5.15.15", "@mui/types": "^7.2.14", "@mui/utils": "^5.15.14", "@types/react-transition-group": "^4.4.10", @@ -10406,9 +10406,9 @@ } }, "@mui/system": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.14.tgz", - "integrity": "sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz", + "integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==", "requires": { "@babel/runtime": "^7.23.9", "@mui/private-theming": "^5.15.14", diff --git a/package.json b/package.json index be52051750..5d18f2aa0b 100644 --- a/package.json +++ b/package.json @@ -51,9 +51,9 @@ "@fortawesome/free-brands-svg-icons": "6.5.2", "@fortawesome/free-solid-svg-icons": "6.5.2", "@fortawesome/react-fontawesome": "0.2.0", - "@mui/icons-material": "5.15.14", - "@mui/lab": "5.0.0-alpha.169", - "@mui/material": "5.15.14", + "@mui/icons-material": "5.15.15", + "@mui/lab": "5.0.0-alpha.170", + "@mui/material": "5.15.15", "@mui/x-date-pickers": "5.0.20", "@reduxjs/toolkit": "1.9.7", "axios": "1.6.8", From ed337eca62dfac48c827c324ddaeb96ea8cf937f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 03:30:43 +0000 Subject: [PATCH 11/19] chore(deps): update dependency css-loader to v6.11.0 (#1042) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 62 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index b24947fca6..9772b8ebac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "@svgr/webpack": "6.5.1", "babel-loader": "9.1.3", "babel-preset-react": "6.24.1", - "css-loader": "6.10.0", + "css-loader": "6.11.0", "file-loader": "6.2.0", "html-webpack-plugin": "5.6.0", "style-loader": "3.3.4", @@ -4475,16 +4475,16 @@ } }, "node_modules/css-loader": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", - "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.4", - "postcss-modules-scope": "^3.1.1", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.5.4" @@ -6945,9 +6945,9 @@ } }, "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, "engines": { "node": "^10 || ^12 || >= 14" @@ -6957,9 +6957,9 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", - "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, "dependencies": { "icss-utils": "^5.0.0", @@ -6974,9 +6974,9 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", - "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" @@ -11794,16 +11794,16 @@ } }, "css-loader": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", - "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dev": true, "requires": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.4", - "postcss-modules-scope": "^3.1.1", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.5.4" @@ -13590,16 +13590,16 @@ } }, "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, "requires": {} }, "postcss-modules-local-by-default": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", - "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, "requires": { "icss-utils": "^5.0.0", @@ -13608,9 +13608,9 @@ } }, "postcss-modules-scope": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", - "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, "requires": { "postcss-selector-parser": "^6.0.4" diff --git a/package.json b/package.json index 5d18f2aa0b..03a34beb12 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@svgr/webpack": "6.5.1", "babel-loader": "9.1.3", "babel-preset-react": "6.24.1", - "css-loader": "6.10.0", + "css-loader": "6.11.0", "file-loader": "6.2.0", "html-webpack-plugin": "5.6.0", "style-loader": "3.3.4", From 292ffec5ae06637cb11b1c73b2bc86da33da48c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 08:23:07 +0000 Subject: [PATCH 12/19] fix(deps): update module github.com/antchfx/xmlquery to v1.4.0 (#1043) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index ef7399c541..406dba8807 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.22.2 require ( github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 - github.com/antchfx/xmlquery v1.3.18 + 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 @@ -54,7 +54,7 @@ require ( github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/PuerkitoBio/goquery v1.5.1 // indirect github.com/andybalholm/cascadia v1.1.0 // indirect - github.com/antchfx/xpath v1.2.4 // indirect + github.com/antchfx/xpath v1.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cloudflare/circl v1.3.3 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect diff --git a/go.sum b/go.sum index 195d01f9c5..5f2b9ac701 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,12 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antchfx/xmlquery v1.3.18 h1:FSQ3wMuphnPPGJOFhvc+cRQ2CT/rUj4cyQXkJcjOwz0= github.com/antchfx/xmlquery v1.3.18/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7TunF7noreA= +github.com/antchfx/xmlquery v1.4.0 h1:xg2HkfcRK2TeTbdb0m1jxCYnvsPaGY/oeZWTGqX/0hA= +github.com/antchfx/xmlquery v1.4.0/go.mod h1:Ax2aeaeDjfIw3CwXKDQ0GkwZ6QlxoChlIBP+mGnDFjI= github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY= github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/antchfx/xpath v1.3.0 h1:nTMlzGAK3IJ0bPpME2urTuFL76o4A96iYvoKFHRXJgc= +github.com/antchfx/xpath v1.3.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= From ce0d2740f93e77d7312735dec89fd61b28dad279 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Thu, 18 Apr 2024 12:26:39 -0400 Subject: [PATCH 13/19] runtime: Support applets with multiple Starlark files (#1041) With `NewAppletFromFS`, process all the Starlark files in the root directory to look for `main()` and `schema()` functions. Also allow files to load other Starlark files. --- runtime/applet.go | 304 +++++++++++++++++++++++++++-------------- runtime/applet_test.go | 124 ++++++++++++++--- runtime/render_test.go | 6 +- 3 files changed, 310 insertions(+), 124 deletions(-) diff --git a/runtime/applet.go b/runtime/applet.go index fc8d731cea..c515515f69 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -2,11 +2,14 @@ package runtime import ( "context" - "crypto/md5" "encoding/json" "fmt" + "io/fs" + "path/filepath" + "slices" "strings" "testing" + "testing/fstest" starlibgzip "github.com/qri-io/starlib/compress/gzip" starlibbase64 "github.com/qri-io/starlib/encoding/base64" @@ -51,13 +54,15 @@ type ThreadInitializer func(thread *starlark.Thread) *starlark.Thread type Applet struct { ID string - src []byte loader ModuleLoader initializers []ThreadInitializer - globals starlark.StringDict - main *starlark.Function + globals map[string]starlark.StringDict + mainFile string + mainFun *starlark.Function + + schemaFile string schema *schema.Schema schemaJSON []byte } @@ -69,13 +74,6 @@ func WithModuleLoader(loader ModuleLoader) AppletOption { } } -func WithThreadInitializer(initializer ThreadInitializer) AppletOption { - return func(a *Applet) error { - a.initializers = append(a.initializers, initializer) - return nil - } -} - func WithSecretDecryptionKey(key *SecretDecryptionKey) AppletOption { return func(a *Applet) error { if decrypter, err := key.decrypterForApp(a); err != nil { @@ -105,9 +103,24 @@ func WithPrintDisabled() AppletOption { } func NewApplet(id string, src []byte, opts ...AppletOption) (*Applet, error) { + fn := id + if !strings.HasSuffix(fn, ".star") { + fn += ".star" + } + + vfs := fstest.MapFS{ + fn: &fstest.MapFile{ + Data: src, + }, + } + + return NewAppletFromFS(id, vfs, opts...) +} + +func NewAppletFromFS(id string, fsys fs.FS, opts ...AppletOption) (*Applet, error) { a := &Applet{ - ID: id, - src: src, + ID: id, + globals: make(map[string]starlark.StringDict), } for _, opt := range opts { @@ -116,70 +129,13 @@ func NewApplet(id string, src []byte, opts ...AppletOption) (*Applet, error) { } } - if err := a.load(); err != nil { + if err := a.load(fsys); err != nil { return nil, err } return a, nil } -func (a *Applet) load() (err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("panic while executing %s: %v", a.ID, r) - } - }() - - predeclared := starlark.StringDict{ - "struct": starlark.NewBuiltin("struct", starlarkstruct.Make), - } - - globals, err := starlark.ExecFileOptions( - &syntax.FileOptions{ - Set: true, - Recursion: true, - }, - a.newThread(context.Background()), - a.ID, - a.src, - predeclared, - ) - if err != nil { - return fmt.Errorf("starlark.ExecFile: %v", err) - } - a.globals = globals - - mainFun, found := globals["main"] - if !found { - return fmt.Errorf("%s didn't export a main() function", a.ID) - } - main, ok := mainFun.(*starlark.Function) - if !ok { - return fmt.Errorf("%s exported a main() that is not function", a.ID) - } - a.main = main - - schemaFun, _ := a.globals[schema.SchemaFunctionName].(*starlark.Function) - if schemaFun != nil { - schemaVal, err := a.Call(context.Background(), schemaFun) - if err != nil { - return fmt.Errorf("calling schema function for %s: %w", a.ID, err) - } - - a.schema, err = schema.FromStarlark(schemaVal, a.globals) - if err != nil { - return fmt.Errorf("parsing schema for %s: %w", a.ID, err) - } - - a.schemaJSON, err = json.Marshal(a.schema) - if err != nil { - return fmt.Errorf("serializing schema to JSON for %s: %w", a.ID, err) - } - } - - return nil -} - // Run executes the applet's main function. It returns the render roots that are // returned by the applet. func (a *Applet) Run(ctx context.Context) (roots []render.Root, err error) { @@ -190,12 +146,12 @@ func (a *Applet) Run(ctx context.Context) (roots []render.Root, err error) { // starlark dict. It returns the render roots that are returned by the applet. func (a *Applet) RunWithConfig(ctx context.Context, config map[string]string) (roots []render.Root, err error) { var args starlark.Tuple - if a.main.NumParams() > 0 { + if a.mainFun.NumParams() > 0 { starlarkConfig := AppletConfig(config) args = starlark.Tuple{starlarkConfig} } - returnValue, err := a.Call(ctx, a.main, args...) + returnValue, err := a.Call(ctx, a.mainFun, args...) if err != nil { return nil, err } @@ -253,7 +209,7 @@ func (app *Applet) CallSchemaHandler(ctx context.Context, handlerName, parameter return options, nil case schema.ReturnSchema: - sch, err := schema.FromStarlark(resultVal, app.globals) + sch, err := schema.FromStarlark(resultVal, app.globals[app.schemaFile]) if err != nil { return "", err } @@ -291,18 +247,19 @@ func (app *Applet) RunTests(t *testing.T) { return thread }) - for name, global := range app.globals { - if !strings.HasPrefix(name, "test_") { - continue - } + for file, globals := range app.globals { + for name, global := range globals { + if !strings.HasPrefix(name, "test_") { + continue + } - fun, ok := global.(*starlark.Function) - if ok && fun != app.main { - t.Run(name, func(t *testing.T) { - if _, err := app.Call(context.Background(), fun); err != nil { - t.Error(err) - } - }) + if fun, ok := global.(*starlark.Function); ok { + t.Run(fmt.Sprintf("%s/%s", file, name), func(t *testing.T) { + if _, err := app.Call(context.Background(), fun); err != nil { + t.Error(err) + } + }) + } } } } @@ -339,6 +296,164 @@ func (a *Applet) Call(ctx context.Context, callable *starlark.Function, args ... return resultVal, nil } +func (a *Applet) load(fsys fs.FS) (err error) { + if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, walkDirErr error) error { + if walkDirErr != nil { + return walkDirErr + } + + if d.IsDir() || filepath.Dir(path) != "." { + // only process files in the root directory + return nil + } + + if !strings.HasSuffix(path, ".star") { + // not a starlark file + return nil + } + + return a.ensureLoaded(fsys, path) + }); err != nil { + return err + } + + if a.mainFun == nil { + return fmt.Errorf("no main() function found in %s", a.ID) + } + + return nil +} + +func (a *Applet) ensureLoaded(fsys fs.FS, path string, currentlyLoading ...string) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("panic while executing %s: %v", a.ID, r) + } + }() + + // normalize path so that it can be used as a key + path = filepath.Clean(path) + if _, ok := a.globals[path]; ok { + // already loaded, good to go + return nil + } + + // use the currentlyLoading slice to detect circular dependencies + if slices.Contains(currentlyLoading, path) { + return fmt.Errorf("circular dependency detected: %s -> %s", strings.Join(currentlyLoading, " -> "), path) + } else { + // mark this file as currently loading. if we encounter it again, + // we have a circular dependency. + currentlyLoading = append(currentlyLoading, path) + } + + src, err := fs.ReadFile(fsys, path) + if err != nil { + return fmt.Errorf("reading %s: %v", path, err) + } + + predeclared := starlark.StringDict{ + "struct": starlark.NewBuiltin("struct", starlarkstruct.Make), + } + + thread := a.newThread(context.Background()) + + // override loader to allow loading starlark files + thread.Load = func(thread *starlark.Thread, module string) (starlark.StringDict, error) { + // normalize module path + modulePath := filepath.Clean(module) + + // if the module exists on the filesystem, load it + if _, err := fs.Stat(fsys, modulePath); err == nil { + // ensure the module is loaded, and pass the currentlyLoading slice + // to detect circular dependencies + if err := a.ensureLoaded(fsys, modulePath, currentlyLoading...); err != nil { + return nil, err + } + + if g, ok := a.globals[modulePath]; !ok { + return nil, fmt.Errorf("module %s not loaded", modulePath) + } else { + return g, nil + } + } + + // fallback to default loader + return a.loadModule(thread, module) + } + + globals, err := starlark.ExecFileOptions( + &syntax.FileOptions{ + Set: true, + Recursion: true, + }, + thread, + a.ID, + src, + predeclared, + ) + if err != nil { + return fmt.Errorf("starlark.ExecFile: %v", err) + } + a.globals[path] = globals + + // if the file is in the root directory, check for the main function + // and schema function + mainFun, _ := globals["main"].(*starlark.Function) + if mainFun != nil { + if a.mainFile != "" { + return fmt.Errorf("multiple files with a main() function:\n- %s\n- %s", path, a.mainFile) + } + + a.mainFile = path + a.mainFun = mainFun + } + + schemaFun, _ := globals[schema.SchemaFunctionName].(*starlark.Function) + if schemaFun != nil { + if a.schemaFile != "" { + return fmt.Errorf("multiple files with a %s() function:\n- %s\n- %s", schema.SchemaFunctionName, path, a.schemaFile) + } + a.schemaFile = path + + schemaVal, err := a.Call(context.Background(), schemaFun) + if err != nil { + return fmt.Errorf("calling schema function for %s: %w", a.ID, err) + } + + a.schema, err = schema.FromStarlark(schemaVal, globals) + if err != nil { + return fmt.Errorf("parsing schema for %s: %w", a.ID, err) + } + + a.schemaJSON, err = json.Marshal(a.schema) + if err != nil { + return fmt.Errorf("serializing schema to JSON for %s: %w", a.ID, err) + } + } + + return nil +} + +func (a *Applet) newThread(ctx context.Context) *starlark.Thread { + t := &starlark.Thread{ + Name: a.ID, + Load: a.loadModule, + Print: func(thread *starlark.Thread, msg string) { + fmt.Printf("[%s] %s\n", a.ID, msg) + }, + } + + starlarkutil.AttachThreadContext(ctx, t) + random.AttachToThread(t) + + for _, init := range a.initializers { + t = init(t) + } + + return t +} + func (a *Applet) loadModule(thread *starlark.Thread, module string) (starlark.StringDict, error) { if a.loader != nil { mod, err := a.loader(thread, module) @@ -439,22 +554,3 @@ func (a *Applet) loadModule(thread *starlark.Thread, module string) (starlark.St return nil, fmt.Errorf("invalid module: %s", module) } } - -func (a *Applet) newThread(ctx context.Context) *starlark.Thread { - t := &starlark.Thread{ - Name: fmt.Sprintf("%s/%x", a.ID, md5.Sum(a.src)), - Load: a.loadModule, - Print: func(thread *starlark.Thread, msg string) { - fmt.Printf("[%s] %s\n", a.ID, msg) - }, - } - - starlarkutil.AttachThreadContext(ctx, t) - random.AttachToThread(t) - - for _, init := range a.initializers { - t = init(t) - } - - return t -} diff --git a/runtime/applet_test.go b/runtime/applet_test.go index 7997d03331..6ba07d8af6 100644 --- a/runtime/applet_test.go +++ b/runtime/applet_test.go @@ -4,13 +4,16 @@ import ( "archive/zip" "bytes" "context" + "encoding/json" "fmt" "testing" + "testing/fstest" starlibbase64 "github.com/qri-io/starlib/encoding/base64" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.starlark.net/starlark" + "tidbyt.dev/pixlet/schema" ) func TestLoadEmptySrc(t *testing.T) { @@ -173,6 +176,47 @@ def main(config): assert.Equal(t, 3, len(roots)) } +func TestLoadMultipleFiles(t *testing.T) { + mainSrc := ` +load("render.star", "render") +def main(): + return render.Root(child=render.Box()) +` + schemaDefSrc := ` +load("schema.star", "schema") +def get_schema(): + return schema.Schema( + version = "1", + fields = [], + ) +` + vfs := fstest.MapFS{ + "main.star": {Data: []byte(mainSrc)}, + "schema_def.star": {Data: []byte(schemaDefSrc)}, + } + + app, err := NewAppletFromFS("multiple_files", vfs) + require.NoError(t, err) + require.NotNil(t, app) + + jsonSchema := app.GetSchema() + var s schema.Schema + json.Unmarshal([]byte(jsonSchema), &s) + assert.Equal(t, "1", s.Version) + + roots, err := app.Run(context.Background()) + assert.NoError(t, err) + assert.NotNil(t, roots) + assert.Equal(t, 1, len(roots)) + + // multiple main functions should fail + vfs["main2.star"] = &fstest.MapFile{ + Data: []byte(mainSrc), + } + _, err = NewAppletFromFS("multiple_files_multiple_mains", vfs) + assert.Error(t, err) +} + func TestModuleLoading(t *testing.T) { // Our basic set of modules can be imported src := ` @@ -230,33 +274,79 @@ def main(): roots, err = app.Run(context.Background()) assert.NoError(t, err) assert.Equal(t, 1, len(roots)) - } -func TestThreadInitializer(t *testing.T) { +func TestDependency(t *testing.T) { + // src.star depends on hello.star src := ` load("render.star", "render") +load("hello.star", "hello") + def main(): - print('foobar') - return render.Root(child=render.Box()) + if hello.world() != "hello world": + fail("something went wrong") + return render.Root(child=render.Box()) ` - // override the print function of the thread - var printedText string - initializer := func(thread *starlark.Thread) *starlark.Thread { - thread.Print = func(thread *starlark.Thread, msg string) { - printedText += msg - } - return thread + + helloSrc := ` +def _world(): + return "hello world" + +hello = struct( + world = _world, +) +` + + vfs := fstest.MapFS{ + "src.star": {Data: []byte(src)}, + "hello.star": {Data: []byte(helloSrc)}, } - app, err := NewApplet("test.star", []byte(src), WithThreadInitializer(initializer)) - assert.NoError(t, err) - assert.NotNil(t, app) - _, err = app.Run(context.Background()) + app, err := NewAppletFromFS("test", vfs) assert.NoError(t, err) + if assert.NotNil(t, app) { + roots, err := app.Run(context.Background()) + assert.NoError(t, err) + assert.Equal(t, 1, len(roots)) + } - // our print function should have been called - assert.Equal(t, "foobar", printedText) + // src2.star shouldn't be able to access private function from hello.star + src2 := ` +load("render.star", "render") +load("hello.star", "_world") + +def main(): + return render.Root(child=render.Box()) + ` + + vfs2 := fstest.MapFS{ + "src2.star": {Data: []byte(src2)}, + "hello.star": {Data: []byte(helloSrc)}, + } + + _, err = NewAppletFromFS("test", vfs2) + assert.ErrorContains(t, err, "not exported") +} + +func TestCircularDependency(t *testing.T) { + // Module A depends on module B + srcA := ` +load("b.star", "b") +def a(): + return b.b() +` + // Module B depends on module A + srcB := ` +load("a.star", "a") +def b(): + return a.a() +` + vfs := fstest.MapFS{ + "a.star": {Data: []byte(srcA)}, + "b.star": {Data: []byte(srcB)}, + } + _, err := NewAppletFromFS("circular_dependency", vfs) + assert.ErrorContains(t, err, "circular dependency") } func TestTimezoneDatabase(t *testing.T) { diff --git a/runtime/render_test.go b/runtime/render_test.go index 961c58b3dd..68117e8816 100644 --- a/runtime/render_test.go +++ b/runtime/render_test.go @@ -161,7 +161,7 @@ def main(): app, err := NewApplet(filename, []byte(src)) assert.NoError(t, err) - b := app.globals["b"] + b := app.globals["test_box.star"]["b"] assert.IsType(t, &render_runtime.Box{}, b) widget := b.(*render_runtime.Box).AsRenderWidget() @@ -196,7 +196,7 @@ def main(): app, err := NewApplet(filename, []byte(src)) assert.NoError(t, err) - txt := app.globals["t"] + txt := app.globals["test_text.star"]["t"] assert.IsType(t, &render_runtime.Text{}, txt) widget := txt.(*render_runtime.Text).AsRenderWidget() @@ -240,7 +240,7 @@ def main(): app, err := NewApplet(filename, []byte(src)) assert.NoError(t, err) - starlarkP := app.globals["img"] + starlarkP := app.globals["test_png.star"]["img"] require.IsType(t, &render_runtime.Image{}, starlarkP) actualIm := render.PaintWidget(starlarkP.(*render_runtime.Image).AsRenderWidget(), image.Rect(0, 0, 64, 32), 0) From 0baa5881410c61da0282eae29769abe244d12025 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 16:32:23 +0000 Subject: [PATCH 14/19] fix(deps): update module github.com/go-git/go-git/v5 to v5.12.0 (#1044) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 11 +++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 406dba8807..ad3de6e38e 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/fatih/color v1.16.0 github.com/fsnotify/fsnotify v1.7.0 github.com/gitsight/go-vcsurl v1.0.1 - github.com/go-git/go-git/v5 v5.11.0 + github.com/go-git/go-git/v5 v5.12.0 github.com/go-playground/validator/v10 v10.15.1 github.com/google/pprof v0.0.0-20240416155748-26353dc0451f github.com/google/tink/go v1.7.0 @@ -51,12 +51,12 @@ require ( dario.cat/mergo v1.0.0 // indirect github.com/Code-Hex/go-wordwrap v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/PuerkitoBio/goquery v1.5.1 // indirect github.com/andybalholm/cascadia v1.1.0 // indirect github.com/antchfx/xpath v1.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -87,8 +87,8 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sergi/go-diff v1.1.0 // indirect - github.com/skeema/knownhosts v1.2.1 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect diff --git a/go.sum b/go.sum index 5f2b9ac701..4f67882d75 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -59,6 +61,8 @@ github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -107,6 +111,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -283,12 +289,16 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -518,6 +528,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 757a72afb62fd1d4763da3e1c1ef2701a648fe18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 18:40:02 +0000 Subject: [PATCH 15/19] fix(deps): update module golang.org/x/oauth2 to v0.19.0 (#1046) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index ad3de6e38e..7b9f152072 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/zachomedia/go-bdf v0.0.0-20220611021443-a3af701111be go.starlark.net v0.0.0-20240411212711-9b43f0afd521 golang.org/x/image v0.15.0 - golang.org/x/oauth2 v0.18.0 + golang.org/x/oauth2 v0.19.0 golang.org/x/sync v0.7.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 4f67882d75..cb7658d840 100644 --- a/go.sum +++ b/go.sum @@ -418,6 +418,8 @@ golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From fe59c716a9aa53f1683a2aed009a0101ffd13f62 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Wed, 24 Apr 2024 06:22:59 -0400 Subject: [PATCH 16/19] Add the ability to read files from Starlark (#1045) * Add the ability to read files from Starlark Starlark scripts can now load arbitrary files from their bundle and read them using a Python-like `open()` and `read()` API. A `readall()` convenience function is also provided. The examples have been updated to use this functionality where relevant. For example: ``` load("icon.png", icon = "file") BTC_ICON = icon.readall() ``` The `pixlet render` command can now accept an entire directory containing multiple Starlark files and static resources. * Remove `file.open` and `read()` Remove the `open()` and `read()` functions, so the only way to read a file is `readall()`. If there is demand for the other methods, we can add them back later. * Add directory support to `pixlet serve` * Implement `pixlet bundle` for directories * Fix path problems on Windows `fs.FS` always uses slash-separated paths, even on Windows. So we should be manipulating those paths with `path`, not `filepath`. * Switch tarfs implementations for Windows support It appears that `nlepage/go-tarfs` correctly supports Windows by [using `path` instead of `filepath`][1]. [1]: https://github.com/nlepage/go-tarfs/pull/7 --- .gitignore | 4 +- README.md | 10 +- bundle/bundle.go | 147 ++++++++---------- bundle/bundle_test.go | 24 ++- bundle/testdata/testapp/a_subdirectory/hi.jpg | Bin 0 -> 32762 bytes bundle/testdata/testapp/manifest.yaml | 2 - bundle/testdata/testapp/test_app.star | 6 + bundle/testdata/testapp/unused.txt | 1 + cmd/community/manifestprompt.go | 12 +- cmd/community/validatemanifest.go | 5 - cmd/render.go | 55 +++++-- cmd/serve.go | 9 +- docs/modules.md | 6 +- docs/tutorial.md | 8 +- examples/{ => bitcoin}/bitcoin.star | 9 +- examples/bitcoin/icon.png | Bin 0 -> 207 bytes examples/{ => clock}/clock.star | 0 examples/{ => font-preview}/font-preview.star | 0 examples/{ => hello_world}/hello_world.star | 0 examples/{ => humanize}/humanize.star | 0 examples/life/gosper_glider.txt | 42 +++++ examples/{ => life}/life.star | 4 +- examples/{ => qrcode}/qrcode.star | 0 examples/{ => quadrants}/quadrants.star | 0 .../schema_hello_world.star | 0 examples/{ => sunrise}/sunrise.star | 0 go.mod | 6 +- go.sum | 38 +---- main.go | 1 - main_nonjs.go | 1 + manifest/manifest.go | 29 ++-- manifest/manifest_test.go | 34 ++-- manifest/testdata/manifest.yaml | 2 - manifest/validate.go | 43 ----- manifest/validate_test.go | 52 ------- runtime/applet.go | 141 ++++++++++------- runtime/file.go | 112 +++++++++++++ runtime/file_test.go | 39 +++++ server/loader/loader.go | 13 +- server/loader/script.go | 14 +- server/loader/script_js.go | 26 ---- server/server.go | 35 ++++- server/{watcher/fs.go => watcher.go} | 32 +++- server/watcher/fs_js.go | 11 -- server/watcher/watcher.go | 21 --- starlarkutil/onexit.go | 27 ++++ tools/generator/generator.go | 13 +- tools/singlefilefs.go | 27 ++++ 48 files changed, 606 insertions(+), 455 deletions(-) create mode 100644 bundle/testdata/testapp/a_subdirectory/hi.jpg create mode 100644 bundle/testdata/testapp/unused.txt rename examples/{ => bitcoin}/bitcoin.star (67%) create mode 100644 examples/bitcoin/icon.png rename examples/{ => clock}/clock.star (100%) rename examples/{ => font-preview}/font-preview.star (100%) rename examples/{ => hello_world}/hello_world.star (100%) rename examples/{ => humanize}/humanize.star (100%) create mode 100644 examples/life/gosper_glider.txt rename examples/{ => life}/life.star (62%) rename examples/{ => qrcode}/qrcode.star (100%) rename examples/{ => quadrants}/quadrants.star (100%) rename examples/{ => schema_hello_world}/schema_hello_world.star (100%) rename examples/{ => sunrise}/sunrise.star (100%) create mode 100644 runtime/file.go create mode 100644 runtime/file_test.go delete mode 100644 server/loader/script_js.go rename server/{watcher/fs.go => watcher.go} (63%) delete mode 100644 server/watcher/fs_js.go delete mode 100644 server/watcher/watcher.go create mode 100644 starlarkutil/onexit.go create mode 100644 tools/singlefilefs.go diff --git a/.gitignore b/.gitignore index 672c066f1f..659fc01ffc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ .DS_Store # Rendered Apps -examples/*.webp -examples/*.gif +examples/**/*.webp +examples/**/*.gif # Pixlet Binary pixlet diff --git a/README.md b/README.md index d998a22ec9..0fade81e60 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ def main(): Render and serve it with: ```console -curl https://raw.githubusercontent.com/tidbyt/pixlet/main/examples/hello_world.star | \ +curl https://raw.githubusercontent.com/tidbyt/pixlet/main/examples/hello_world/hello_world.star | \ pixlet serve /dev/stdin ``` @@ -135,7 +135,7 @@ to show the Bitcoin tracker on your Tidbyt: ```console # render the bitcoin example -pixlet render examples/bitcoin.star +pixlet render examples/bitcoin/bitcoin.star # login to your Tidbyt account pixlet login @@ -144,7 +144,7 @@ pixlet login pixlet devices # push to your favorite Tidbyt -pixlet push examples/bitcoin.webp +pixlet push examples/bitcoin/bitcoin.webp ``` To get the ID for a device, run `pixlet devices`. Alternatively, you can @@ -158,8 +158,8 @@ If all goes well, you should see the Bitcoin tracker appear on your Tidbyt: Pushing an applet to your Tidbyt without an installation ID simply displays your applet one time. If you would like your applet to continously display as part of the rotation, add an installation ID to the push command: ```console -pixlet render examples/bitcoin.star -pixlet push --installation-id examples/bitcoin.webp +pixlet render examples/bitcoin/bitcoin.star +pixlet push --installation-id examples/bitcoin/bitcoin.webp ``` For example, if we set the `installationID` to "Bitcoin", it would appear in the mobile app as follows: diff --git a/bundle/bundle.go b/bundle/bundle.go index 5c4c4c211b..fe777de1ee 100644 --- a/bundle/bundle.go +++ b/bundle/bundle.go @@ -7,10 +7,14 @@ import ( "compress/gzip" "fmt" "io" + "io/fs" "os" "path/filepath" + "github.com/nlepage/go-tarfs" + "tidbyt.dev/pixlet/manifest" + "tidbyt.dev/pixlet/runtime" ) const ( @@ -26,16 +30,12 @@ const ( // AppBundle represents the unpacked bundle in our system. type AppBundle struct { - Source []byte Manifest *manifest.Manifest + Source fs.FS } -// InitFromPath translates a directory containing an app manifest and source -// into an AppBundle. -func InitFromPath(dir string) (*AppBundle, error) { - // Load manifest - path := filepath.Join(dir, manifest.ManifestFileName) - m, err := os.Open(path) +func fromFS(fs fs.FS) (*AppBundle, error) { + m, err := fs.Open(manifest.ManifestFileName) if err != nil { return nil, fmt.Errorf("could not open manifest: %w", err) } @@ -46,80 +46,39 @@ func InitFromPath(dir string) (*AppBundle, error) { return nil, fmt.Errorf("could not load manifest: %w", err) } - // Load source - path = filepath.Join(dir, man.FileName) - s, err := os.Open(path) - if err != nil { - return nil, fmt.Errorf("could not open app source: %w", err) - } - defer s.Close() - - src, err := io.ReadAll(s) - if err != nil { - return nil, fmt.Errorf("could not read app source: %w", err) - } - // Create app bundle struct return &AppBundle{ Manifest: man, - Source: src, + Source: fs, }, nil } +// InitFromPath translates a directory containing an app manifest and source +// into an AppBundle. +func InitFromPath(dir string) (*AppBundle, error) { + return fromFS(os.DirFS(dir)) +} + // LoadBundle loads a compressed archive into an AppBundle. func LoadBundle(in io.Reader) (*AppBundle, error) { gzr, err := gzip.NewReader(in) if err != nil { - return nil, fmt.Errorf("could not create gzip reader: %w", err) + return nil, fmt.Errorf("creating gzip reader: %w", err) } defer gzr.Close() - tr := tar.NewReader(gzr) - ab := &AppBundle{} - - for { - header, err := tr.Next() - - switch { - case err == io.EOF: - // If there are no more files in the bundle, validate and return it. - if ab.Manifest == nil { - return nil, fmt.Errorf("could not find manifest in archive") - } - if ab.Source == nil { - return nil, fmt.Errorf("could not find source in archive") - } - return ab, nil - case err != nil: - // If there is an error, return immediately. - return nil, fmt.Errorf("could not read archive: %w", err) - case header == nil: - // If for some reason we end up with a blank header, continue to the - // next one. - continue - case header.Name == AppSourceName: - // Load the app source. - buff := make([]byte, header.Size) - _, err := io.ReadFull(tr, buff) - if err != nil { - return nil, fmt.Errorf("could not read source from archive: %w", err) - } - ab.Source = buff - case header.Name == manifest.ManifestFileName: - // Load the app manifest. - buff := make([]byte, header.Size) - _, err := io.ReadFull(tr, buff) - if err != nil { - return nil, fmt.Errorf("could not read manifest from archive: %w", err) - } + // read the entire tarball into memory so that we can seek + // around it, and so that the underlying reader can be closed. + var b bytes.Buffer + io.Copy(&b, gzr) - man, err := manifest.LoadManifest(bytes.NewReader(buff)) - if err != nil { - return nil, fmt.Errorf("could not load manifest: %w", err) - } - ab.Manifest = man - } + r := bytes.NewReader(b.Bytes()) + fs, err := tarfs.New(r) + if err != nil { + return nil, fmt.Errorf("creating tarfs: %w", err) } + + return fromFS(fs) } // WriteBundleToPath is a helper to be able to write the bundle to a provided @@ -137,6 +96,16 @@ func (b *AppBundle) WriteBundleToPath(dir string) error { // WriteBundle writes a compressed archive to the provided writer. func (ab *AppBundle) WriteBundle(out io.Writer) error { + // we don't want to naively write the entire source FS to the tarball, + // since it could contain a lot of extraneous files. instead, run the + // applet and interrogate it for the files it needs to include in the + // bundle. + app, err := runtime.NewAppletFromFS(ab.Manifest.ID, ab.Source, runtime.WithPrintDisabled()) + if err != nil { + return fmt.Errorf("loading applet for bundling: %w", err) + } + bundleFiles := app.PathsForBundle() + // Setup writers. gzw := gzip.NewWriter(out) defer gzw.Close() @@ -146,7 +115,7 @@ func (ab *AppBundle) WriteBundle(out io.Writer) error { // Write manifest. buff := &bytes.Buffer{} - err := ab.Manifest.WriteManifest(buff) + err = ab.Manifest.WriteManifest(buff) if err != nil { return fmt.Errorf("could not write manifest to buffer: %w", err) } @@ -166,19 +135,37 @@ func (ab *AppBundle) WriteBundle(out io.Writer) error { return fmt.Errorf("could not write manifest to archive: %w", err) } - // Write source. - hdr = &tar.Header{ - Name: AppSourceName, - Mode: 0600, - Size: int64(len(ab.Source)), - } - err = tw.WriteHeader(hdr) - if err != nil { - return fmt.Errorf("could not write source header: %w", err) - } - _, err = tw.Write(ab.Source) - if err != nil { - return fmt.Errorf("could not write source to archive: %w", err) + // write sources. + for _, path := range bundleFiles { + stat, err := fs.Stat(ab.Source, path) + if err != nil { + return fmt.Errorf("could not stat %s: %w", path, err) + } + + hdr, err := tar.FileInfoHeader(stat, "") + if err != nil { + return fmt.Errorf("creating header for %s: %w", path, err) + } + hdr.Name = filepath.ToSlash(path) + + err = tw.WriteHeader(hdr) + if err != nil { + return fmt.Errorf("writing header for %s: %w", path, err) + } + + if !stat.IsDir() { + file, err := ab.Source.Open(path) + if err != nil { + return fmt.Errorf("opening file %s: %w", path, err) + } + + written, err := io.Copy(tw, file) + if err != nil { + return fmt.Errorf("writing file %s: %w", path, err) + } else if written != stat.Size() { + return fmt.Errorf("did not write entire file %s: %w", path, err) + } + } } return nil diff --git a/bundle/bundle_test.go b/bundle/bundle_test.go index 77e9ffbd37..307a0eb6b1 100644 --- a/bundle/bundle_test.go +++ b/bundle/bundle_test.go @@ -14,7 +14,7 @@ func TestBundleWriteAndLoad(t *testing.T) { ab, err := bundle.InitFromPath("testdata/testapp") assert.NoError(t, err) assert.Equal(t, "test-app", ab.Manifest.ID) - assert.True(t, len(ab.Source) > 0) + assert.NotNil(t, ab.Source) // Create a temp directory. dir, err := os.MkdirTemp("", "") @@ -32,7 +32,23 @@ func TestBundleWriteAndLoad(t *testing.T) { newBun, err := bundle.LoadBundle(f) assert.NoError(t, err) assert.Equal(t, "test-app", newBun.Manifest.ID) - assert.True(t, len(ab.Source) > 0) + assert.NotNil(t, ab.Source) + + // Ensure the loaded bundle contains the files we expect. + filesExpected := []string{ + "manifest.yaml", + "test_app.star", + "test.txt", + "a_subdirectory/hi.jpg", + } + for _, file := range filesExpected { + _, err := newBun.Source.Open(file) + assert.NoError(t, err) + } + + // Ensure the loaded bundle does not contain any extra files. + _, err = newBun.Source.Open("unused.txt") + assert.ErrorIs(t, err, os.ErrNotExist) } func TestLoadBundle(t *testing.T) { f, err := os.Open("testdata/bundle.tar.gz") @@ -41,7 +57,7 @@ func TestLoadBundle(t *testing.T) { ab, err := bundle.LoadBundle(f) assert.NoError(t, err) assert.Equal(t, "test-app", ab.Manifest.ID) - assert.True(t, len(ab.Source) > 0) + assert.NotNil(t, ab.Source) } func TestLoadBundleExcessData(t *testing.T) { f, err := os.Open("testdata/excess-files.tar.gz") @@ -51,5 +67,5 @@ func TestLoadBundleExcessData(t *testing.T) { ab, err := bundle.LoadBundle(f) assert.NoError(t, err) assert.Equal(t, "test-app", ab.Manifest.ID) - assert.True(t, len(ab.Source) > 0) + assert.NotNil(t, ab.Source) } diff --git a/bundle/testdata/testapp/a_subdirectory/hi.jpg b/bundle/testdata/testapp/a_subdirectory/hi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8da8481f2fa0c1e5e9d8cb7438c20ef59c174dd2 GIT binary patch literal 32762 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 SEv$p6`Gq^zj` literal 0 HcmV?d00001 diff --git a/bundle/testdata/testapp/manifest.yaml b/bundle/testdata/testapp/manifest.yaml index f2b10a8a60..630cebcd79 100644 --- a/bundle/testdata/testapp/manifest.yaml +++ b/bundle/testdata/testapp/manifest.yaml @@ -4,5 +4,3 @@ name: Test App summary: For Testing desc: It's an app for testing. author: Test Dev -fileName: test_app.star -packageName: testapp diff --git a/bundle/testdata/testapp/test_app.star b/bundle/testdata/testapp/test_app.star index fc8ae9d840..cee0a6c5bc 100644 --- a/bundle/testdata/testapp/test_app.star +++ b/bundle/testdata/testapp/test_app.star @@ -5,11 +5,17 @@ Description: It's an app for testing. Author: Test Dev """ +load("a_subdirectory/hi.jpg", hi_jpeg = "file") load("render.star", "render") load("schema.star", "schema") +load("test.txt", test_txt = "file") DEFAULT_WHO = "world" +TEST_TXT_CONTENT = test_txt.readall() + +HI_JPEG_BYTES = hi_jpeg.readall("rb") + def main(config): who = config.str("who", DEFAULT_WHO) message = "Hello, {}!".format(who) diff --git a/bundle/testdata/testapp/unused.txt b/bundle/testdata/testapp/unused.txt new file mode 100644 index 0000000000..c3e8caa0b7 --- /dev/null +++ b/bundle/testdata/testapp/unused.txt @@ -0,0 +1 @@ +this file is not used in the app \ No newline at end of file diff --git a/cmd/community/manifestprompt.go b/cmd/community/manifestprompt.go index b2ac75eb47..40c1c73e3c 100644 --- a/cmd/community/manifestprompt.go +++ b/cmd/community/manifestprompt.go @@ -51,12 +51,10 @@ func ManifestPrompt() (*manifest.Manifest, error) { } return &manifest.Manifest{ - ID: manifest.GenerateID(name), - Name: name, - Summary: summary, - Desc: desc, - Author: author, - FileName: manifest.GenerateFileName(name), - PackageName: manifest.GeneratePackageName(name), + ID: manifest.GenerateID(name), + Name: name, + Summary: summary, + Desc: desc, + Author: author, }, nil } diff --git a/cmd/community/validatemanifest.go b/cmd/community/validatemanifest.go index 35c0f90df3..ef475658a4 100644 --- a/cmd/community/validatemanifest.go +++ b/cmd/community/validatemanifest.go @@ -12,7 +12,6 @@ import ( var ValidateManifestAppFileName string func init() { - ValidateManifestCmd.Flags().StringVarP(&ValidateManifestAppFileName, "app-file-name", "a", "", "ensures the app file name is the same as the manifest") } var ValidateManifestCmd = &cobra.Command{ @@ -47,9 +46,5 @@ func ValidateManifest(cmd *cobra.Command, args []string) error { return fmt.Errorf("couldn't validate manifest: %w", err) } - if ValidateManifestAppFileName != "" && m.FileName != ValidateManifestAppFileName { - return fmt.Errorf("app name doesn't match: %s != %s", ValidateManifestAppFileName, m.FileName) - } - return nil } diff --git a/cmd/render.go b/cmd/render.go index d5746ea5ec..d64327c78c 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -4,8 +4,11 @@ import ( "context" "fmt" "image" + "io/fs" "os" + "path/filepath" "strings" + "testing/fstest" "time" "github.com/spf13/cobra" @@ -68,23 +71,49 @@ func init() { } var RenderCmd = &cobra.Command{ - Use: "render [script] [=value>]...", - Short: "Run a Pixlet script with provided config parameters", + Use: "render [path] [=value>]...", + Short: "Run a Pixlet app with provided config parameters", Args: cobra.MinimumNArgs(1), RunE: render, + Long: `Render a Pixlet app with provided config parameters. + +The path argument should be the path to the Pixlet app to run. The +app can be a single file with the .star extension, or a directory +containing multiple Starlark files and resources. + `, } func render(cmd *cobra.Command, args []string) error { - script := args[0] + path := args[0] - globals.Width = width - globals.Height = height + // 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) + } + + var fs fs.FS + var outPath string + if info.IsDir() { + fs = os.DirFS(path) + outPath = filepath.Join(path, filepath.Base(path)) + } else { + if !strings.HasSuffix(path, ".star") { + 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}, + } - if !strings.HasSuffix(script, ".star") { - return fmt.Errorf("script file must have suffix .star: %s", script) + outPath = strings.TrimSuffix(path, ".star") } - outPath := strings.TrimSuffix(script, ".star") if renderGif { outPath += ".gif" } else { @@ -94,6 +123,9 @@ func render(cmd *cobra.Command, args []string) error { outPath = output } + globals.Width = width + globals.Height = height + config := map[string]string{} for _, param := range args[1:] { split := strings.Split(param, "=") @@ -103,11 +135,6 @@ func render(cmd *cobra.Command, args []string) error { config[split[0]] = strings.Join(split[1:], "=") } - src, err := os.ReadFile(script) - if err != nil { - return fmt.Errorf("failed to read file %s: %w", script, err) - } - // Remove the print function from the starlark thread if the silent flag is // passed. var opts []runtime.AppletOption @@ -128,7 +155,7 @@ func render(cmd *cobra.Command, args []string) error { runtime.InitHTTP(cache) runtime.InitCache(cache) - applet, err := runtime.NewApplet(script, src, opts...) + applet, err := runtime.NewAppletFromFS(filepath.Base(path), fs, opts...) if err != nil { return fmt.Errorf("failed to load applet: %w", err) } diff --git a/cmd/serve.go b/cmd/serve.go index 10baa95127..b2bf0c71eb 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -15,16 +15,21 @@ var ( func init() { ServeCmd.Flags().StringVarP(&host, "host", "i", "127.0.0.1", "Host interface for serving rendered images") ServeCmd.Flags().IntVarP(&port, "port", "p", 8080, "Port for serving rendered images") - ServeCmd.Flags().BoolVarP(&watch, "watch", "w", true, "Reload scripts on change") + ServeCmd.Flags().BoolVarP(&watch, "watch", "w", true, "Reload scripts on change. Does not recurse sub-directories.") ServeCmd.Flags().IntVarP(&maxDuration, "max_duration", "d", 15000, "Maximum allowed animation duration (ms)") ServeCmd.Flags().IntVarP(&timeout, "timeout", "", 30000, "Timeout for execution (ms)") } var ServeCmd = &cobra.Command{ - Use: "serve [script]", + Use: "serve [path]", Short: "Serve a Pixlet app in a web server", Args: cobra.ExactArgs(1), RunE: serve, + Long: `Serve a Pixlet app in a web server. + +The path argument should be the path to the Pixlet program to run. The +program can be a single file with the .star extension, or a directory +containing multiple Starlark files and resources.`, } func serve(cmd *cobra.Command, args []string) error { diff --git a/docs/modules.md b/docs/modules.md index 90a80cef7f..a7d05446fd 100644 --- a/docs/modules.md +++ b/docs/modules.md @@ -111,7 +111,7 @@ The `humanize` module has formatters for units to human friendly sizes. Example: -See [examples/humanize.star](../examples/humanize.star) for an example. +See [examples/humanize/humanize.star](../examples/humanize/humanize.star) for an example. ## Pixlet module: XPath @@ -177,7 +177,7 @@ The schema module provides configuration options for your app. See the [schema d Example: -See [examples/schema_hello_world.star](../examples/schema_hello_world.star) for an example. +See [examples/schema_hello_world/schema_hello_world.star](../examples/schema_hello_world/schema_hello_world.star) for an example. ## Pixlet module: Secret @@ -210,7 +210,7 @@ The `sunrise` module calculates sunrise and sunset times for a given set of GPS Example: -See [examples/sunrise.star](../examples/sunrise.star) for an example. +See [examples/sunrise/sunrise.star](../examples/sunrise/sunrise.star) for an example. ## Pixlet module: Random diff --git a/docs/tutorial.md b/docs/tutorial.md index 4375942679..a8ce678e56 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -9,19 +9,19 @@ biased. You should be able to run the Pixlet CLI like so: -`$ pixlet render examples/clock.star` +`$ pixlet render examples/clock/clock.star` This should in turn run `clock.star` and produce a `clock.webp` file. ```console -$ file examples/clock.webp -examples/clock.webp: RIFF (little-endian) data, Web/P image +$ file examples/clock/clock.webp +examples/clock/clock.webp: RIFF (little-endian) data, Web/P image ``` For local development, its often convenient to run pixlet in "serve" mode: -`$ pixlet serve --watch examples/clock.star` +`$ pixlet serve --watch examples/clock/clock.star` Direct your web browser to http://localhost:8080, and your rendered app will appear. diff --git a/examples/bitcoin.star b/examples/bitcoin/bitcoin.star similarity index 67% rename from examples/bitcoin.star rename to examples/bitcoin/bitcoin.star index 19ea6748a1..f24e7ead42 100644 --- a/examples/bitcoin.star +++ b/examples/bitcoin/bitcoin.star @@ -1,15 +1,10 @@ -load("encoding/base64.star", "base64") load("http.star", "http") +load("icon.png", icon = "file") load("render.star", "render") COINDESK_PRICE_URL = "https://api.coindesk.com/v1/bpi/currentprice.json" -BTC_ICON = base64.decode(""" -iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAAlklEQVQ4T2NkwAH+H2T/jy7FaP+ -TEZtyDEG4Zi0TTPXXzoDF0A1DMQRsADbN6MZdO4NiENwQbAbERh1lWLzMmgFGo5iFZBDYEFwuwG -sISCPUIKyGgDRjAyBXYXMNIz5XgDQga8TpLboYgux8DO/AwoUuLiEqTLBFMcmxQ7V0gssgklIsL -AYozjsoBoE45OZi5DRBSnkCAMLhlPBiQGHlAAAAAElFTkSuQmCC -""") +BTC_ICON = icon.readall() def main(): rep = http.get(COINDESK_PRICE_URL, ttl_seconds = 240) diff --git a/examples/bitcoin/icon.png b/examples/bitcoin/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8ffd20791539b4a12697dbd6db62f0c6b1178ae1 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2e8X`U{QAr}70DF+z;$*279*E^c= zf3o20A|A&bX}ZEbU$38QIC_EC*^niN!R+jdW3krFNdk8Sa@dZz$)-l^IWvpVZSjoO z6oDH8F?t8GIXslFD6DB~FiB=s2v02LRkjOnFj2@p@=|w~MAMrZp7#e1wd(09YWZw% zH9Wb|d2312X@yBaIy!6`=d3l@8ZDkYOL}7B=vB$YaOmNb4@nM*Pk}CE@O1TaS?83{ F1OUH$O4I-V literal 0 HcmV?d00001 diff --git a/examples/clock.star b/examples/clock/clock.star similarity index 100% rename from examples/clock.star rename to examples/clock/clock.star diff --git a/examples/font-preview.star b/examples/font-preview/font-preview.star similarity index 100% rename from examples/font-preview.star rename to examples/font-preview/font-preview.star diff --git a/examples/hello_world.star b/examples/hello_world/hello_world.star similarity index 100% rename from examples/hello_world.star rename to examples/hello_world/hello_world.star diff --git a/examples/humanize.star b/examples/humanize/humanize.star similarity index 100% rename from examples/humanize.star rename to examples/humanize/humanize.star diff --git a/examples/life/gosper_glider.txt b/examples/life/gosper_glider.txt new file mode 100644 index 0000000000..8ee81f9968 --- /dev/null +++ b/examples/life/gosper_glider.txt @@ -0,0 +1,42 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 \ No newline at end of file diff --git a/examples/life.star b/examples/life/life.star similarity index 62% rename from examples/life.star rename to examples/life/life.star index d84274ad7b..0691ac0cfb 100644 --- a/examples/life.star +++ b/examples/life/life.star @@ -15,6 +15,7 @@ load("cache.star", "cache") load("encoding/base64.star", "base64") +load("gosper_glider.txt", gosper_glider = "file") load("render.star", "render") load("time.star", "time") @@ -476,5 +477,4 @@ def get_seeded_gosper_glider_board(): method and then base64 encoded. This was a trade off in repeatability with efficiency. I originally rendered this by using points mapped to create the Gosper Glider Gun and running through a few iterations until it looked nice. """ - encoded_board = "MCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMCwxLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDEsMCwxLDAsMCwwLDAsMCwwLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwxLDEsMSwxLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwxLDAsMCwwLDAsMCwwLDEsMCwwLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMCwwLDAsMCwwLDAsMSwwLDAsMCwwLDAsMCwwLDEsMSwwLDAsMCwxLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDEsMCwwLDAsMCwwLDAsMCwwLDEsMCwwLDAsMCwxLDAsMCwwLDAsMCwwLDAsMSwwLDAsMSwwLDAsMCwwLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMSwxLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMSwwLDAsMCwxLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDEsMCwxLDAsMCwwLDAsMCwwLDAsMCwxLDAsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDEsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMSwxLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDEsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAKMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwCjAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMAowLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDA=" - return decode(base64.decode(encoded_board)) + return decode(gosper_glider.readall()) diff --git a/examples/qrcode.star b/examples/qrcode/qrcode.star similarity index 100% rename from examples/qrcode.star rename to examples/qrcode/qrcode.star diff --git a/examples/quadrants.star b/examples/quadrants/quadrants.star similarity index 100% rename from examples/quadrants.star rename to examples/quadrants/quadrants.star diff --git a/examples/schema_hello_world.star b/examples/schema_hello_world/schema_hello_world.star similarity index 100% rename from examples/schema_hello_world.star rename to examples/schema_hello_world/schema_hello_world.star diff --git a/examples/sunrise.star b/examples/sunrise/sunrise.star similarity index 100% rename from examples/sunrise.star rename to examples/sunrise/sunrise.star diff --git a/go.mod b/go.mod index 7b9f152072..485b35137f 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/newm4n/go-dfe v0.0.0-20210113055126-9d5f01722db9 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c + github.com/nlepage/go-tarfs v1.2.1 github.com/nlepage/go-wasm-http-server v1.1.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/qri-io/starlib v0.5.1-0.20220611014110-7fb7ff9ec804 @@ -100,11 +101,10 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.12.0 // indirect + golang.org/x/mod v0.16.0 // indirect golang.org/x/net v0.22.0 // indirect golang.org/x/sys v0.18.0 // indirect - golang.org/x/tools v0.13.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + golang.org/x/tools v0.19.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index cb7658d840..af16291738 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,6 @@ github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE= @@ -23,12 +21,8 @@ github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5z github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antchfx/xmlquery v1.3.18 h1:FSQ3wMuphnPPGJOFhvc+cRQ2CT/rUj4cyQXkJcjOwz0= -github.com/antchfx/xmlquery v1.3.18/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7TunF7noreA= github.com/antchfx/xmlquery v1.4.0 h1:xg2HkfcRK2TeTbdb0m1jxCYnvsPaGY/oeZWTGqX/0hA= github.com/antchfx/xmlquery v1.4.0/go.mod h1:Ax2aeaeDjfIw3CwXKDQ0GkwZ6QlxoChlIBP+mGnDFjI= -github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY= -github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antchfx/xpath v1.3.0 h1:nTMlzGAK3IJ0bPpME2urTuFL76o4A96iYvoKFHRXJgc= github.com/antchfx/xpath v1.3.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -59,7 +53,6 @@ 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 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= @@ -101,16 +94,14 @@ github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gitsight/go-vcsurl v1.0.1 h1:wkijKsbVg9R2IBP97U7wOANeIW9WJJKkBwS9XqllzWo= github.com/gitsight/go-vcsurl v1.0.1/go.mod h1:qRFdKDa/0Lh9MT0xE+qQBYZ/01+mY1H40rZUHR24X9U= -github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= -github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= -github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -165,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-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY= -github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= 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/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= @@ -243,6 +232,8 @@ github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4 github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c/go.mod h1:DvuJJ/w1Y59rG8UTDxsMk5U+UJXJwuvUgbiJSm9yhX8= github.com/nlepage/go-js-promise v1.0.0 h1:K7OmJ3+0BgWJ2LfXchg2sI6RDr7AW/KWR8182epFwGQ= github.com/nlepage/go-js-promise v1.0.0/go.mod h1:bdOP0wObXu34euibyK39K1hoBCtlgTKXGc56AGflaRo= +github.com/nlepage/go-tarfs v1.2.1 h1:o37+JPA+ajllGKSPfy5+YpsNHDjZnAoyfvf5GsUa+Ks= +github.com/nlepage/go-tarfs v1.2.1/go.mod h1:rno18mpMy9aEH1IiJVftFsqPyIpwqSUiAOpJYjlV2NA= github.com/nlepage/go-wasm-http-server v1.1.0 h1:phw2NtSp71m/6NmGjE2veQ41PBPzWFcnE614cKucy5M= github.com/nlepage/go-wasm-http-server v1.1.0/go.mod h1:xpffUeN97vuv8CTlMJ2oC5tPsftfPoG9HkAgI9gkiPI= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -287,16 +278,12 @@ github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgY github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= @@ -362,8 +349,6 @@ github.com/zachomedia/go-bdf v0.0.0-20220611021443-a3af701111be/go.mod h1:FWqHpm go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= -go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a h1:Oe+v9w90BBIxQZ4U39+axR8KxrBbxqnRudPPcBIlP3o= -go.starlark.net v0.0.0-20240329153429-e6e8e7ce1b7a/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.starlark.net v0.0.0-20240411212711-9b43f0afd521 h1:1Ufp2S2fPpj0RHIQ4rbzpCdPLCPkzdK7BaVFH3nkYBQ= go.starlark.net v0.0.0-20240411212711-9b43f0afd521/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -392,8 +377,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -402,7 +387,6 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -416,8 +400,6 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -463,7 +445,6 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -483,15 +464,13 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= @@ -528,7 +507,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index f2f64cfbc0..153d62edba 100644 --- a/main.go +++ b/main.go @@ -18,7 +18,6 @@ var ( ) func init() { - rootCmd.AddCommand(cmd.ServeCmd) rootCmd.AddCommand(cmd.RenderCmd) rootCmd.AddCommand(cmd.PushCmd) rootCmd.AddCommand(cmd.EncryptCmd) diff --git a/main_nonjs.go b/main_nonjs.go index 2f82271f3a..5125a866ac 100644 --- a/main_nonjs.go +++ b/main_nonjs.go @@ -10,4 +10,5 @@ import ( func init() { rootCmd.AddCommand(private.PrivateCmd) rootCmd.AddCommand(cmd.CreateCmd) + rootCmd.AddCommand(cmd.ServeCmd) } diff --git a/manifest/manifest.go b/manifest/manifest.go index bfa0281318..9b32885aa3 100644 --- a/manifest/manifest.go +++ b/manifest/manifest.go @@ -16,21 +16,22 @@ type Manifest struct { // ID is the unique identifier of this app. It has to be globally unique, // which means it cannot conflict with any of our private apps. ID string `json:"id" yaml:"id"` + // Name is the name of the applet. Ex. "Fuzzy Clock" Name string `json:"name" yaml:"name"` + // Summary is the short form of what this applet does. Ex. "Human readable // time". Summary string `json:"summary" yaml:"summary"` + // Desc is the long form of what this applet does. Ex. "Display the time in // a groovy, human-readable way." Desc string `json:"desc" yaml:"desc"` + // Author is the person or organization who contributed this applet. Ex, // "Max Timkovich" Author string `json:"author" yaml:"author"` - // FileName is the name of the starlark source file. - FileName string `json:"fileName" yaml:"fileName"` - // PackageName is the name of the go package where this app lives. - PackageName string `json:"packageName" yaml:"packageName"` + // Source is the starlark source code for this applet using the go `embed` // module. Source []byte `json:"-" yaml:"-"` @@ -100,24 +101,14 @@ func (m Manifest) Validate() error { return err } - err = ValidateFileName(m.FileName) - if err != nil { - return err - } - - err = ValidatePackageName(m.PackageName) - if err != nil { - return err - } - return nil } -// GeneratePackageName creates a suitable go package name from an app name. -func GeneratePackageName(name string) string { - packageName := strings.ReplaceAll(name, "-", "") - packageName = strings.ReplaceAll(packageName, "_", "") - return strings.ToLower(strings.Join(strings.Fields(packageName), "")) +// GenerateDirName creates a suitable directory name from an app name. +func GenerateDirName(name string) string { + dir := strings.ReplaceAll(name, "-", "") + dir = strings.ReplaceAll(dir, "_", "") + return strings.ToLower(strings.Join(strings.Fields(dir), "")) } // GenerateID creates a suitable ID from an app name. diff --git a/manifest/manifest_test.go b/manifest/manifest_test.go index 57d8429d91..a29101046b 100644 --- a/manifest/manifest_test.go +++ b/manifest/manifest_test.go @@ -21,20 +21,16 @@ name: Foo Tracker summary: Track realtime foo desc: The foo tracker provides realtime feeds for foo. author: Tidbyt -fileName: foo_tracker.star -packageName: footracker ` func TestManifest(t *testing.T) { m := manifest.Manifest{ - ID: "foo-tracker", - Name: "Foo Tracker", - Summary: "Track realtime foo", - Desc: "The foo tracker provides realtime feeds for foo.", - Author: "Tidbyt", - FileName: "foo_tracker.star", - PackageName: "footracker", - Source: source, + ID: "foo-tracker", + Name: "Foo Tracker", + Summary: "Track realtime foo", + Desc: "The foo tracker provides realtime feeds for foo.", + Author: "Tidbyt", + Source: source, } expected, err := os.ReadFile("testdata/source.star") @@ -56,20 +52,16 @@ func TestLoadManifest(t *testing.T) { assert.Equal(t, m.Author, "Max Timkovich") assert.Equal(t, m.Summary, "Human readable time") assert.Equal(t, m.Desc, "Display the time in a groovy, human-readable way.") - assert.Equal(t, m.FileName, "fuzzy_clock.star") - assert.Equal(t, m.PackageName, "fuzzyclock") } func TestWriteManifest(t *testing.T) { m := manifest.Manifest{ - ID: "foo-tracker", - Name: "Foo Tracker", - Summary: "Track realtime foo", - Desc: "The foo tracker provides realtime feeds for foo.", - Author: "Tidbyt", - FileName: "foo_tracker.star", - PackageName: "footracker", - Source: source, + ID: "foo-tracker", + Name: "Foo Tracker", + Summary: "Track realtime foo", + Desc: "The foo tracker provides realtime feeds for foo.", + Author: "Tidbyt", + Source: source, } buff := bytes.Buffer{} @@ -96,7 +88,7 @@ func TestGeneratePackageName(t *testing.T) { } for _, tc := range tests { - got := manifest.GeneratePackageName(tc.input) + got := manifest.GenerateDirName(tc.input) assert.Equal(t, tc.want, got) } } diff --git a/manifest/testdata/manifest.yaml b/manifest/testdata/manifest.yaml index 7f3254a77d..6e2f0e2f0c 100644 --- a/manifest/testdata/manifest.yaml +++ b/manifest/testdata/manifest.yaml @@ -4,5 +4,3 @@ name: Fuzzy Clock summary: Human readable time desc: Display the time in a groovy, human-readable way. author: Max Timkovich -fileName: fuzzy_clock.star -packageName: fuzzyclock diff --git a/manifest/validate.go b/manifest/validate.go index 27f2e3650c..fddc036b0d 100644 --- a/manifest/validate.go +++ b/manifest/validate.go @@ -119,49 +119,6 @@ func ValidateAuthor(author string) error { return nil } -func ValidatePackageName(packageName string) error { - if packageName == "" { - return fmt.Errorf("package names cannot be empty") - } - - if packageName != strings.ToLower(packageName) { - return fmt.Errorf("package names should be lower case") - } - - for _, r := range packageName { - if !(unicode.IsLetter(r) || unicode.IsNumber(r)) { - return fmt.Errorf("package names can only contain letters, numbers, or an underscore character") - } - } - return nil -} - -// ValidateFileName ensures the file name appears appropriately for starlark -// source code. -func ValidateFileName(fileName string) error { - if fileName == "" { - return fmt.Errorf("fileName cannot be empty") - } - - if !strings.HasSuffix(fileName, ".star") { - return fmt.Errorf("file names should end in .star: '%s'", fileName) - } - - testName := strings.TrimSuffix(fileName, ".star") - - if testName != strings.ToLower(testName) { - return fmt.Errorf("file names should be lower case") - } - - for _, r := range testName { - if !(unicode.IsLetter(r) || unicode.IsNumber(r) || r == underscore) { - return fmt.Errorf("file names can only contain letters, numbers, or an underscore character") - } - } - - return nil -} - // ValidateID ensures the id will parse when we go to add it to our database // internally. func ValidateID(id string) error { diff --git a/manifest/validate_test.go b/manifest/validate_test.go index f960d4dfa5..e5d5f2648a 100644 --- a/manifest/validate_test.go +++ b/manifest/validate_test.go @@ -111,55 +111,3 @@ func TestValidateID(t *testing.T) { } } - -func TestValidateFileName(t *testing.T) { - type test struct { - input string - shouldErr bool - } - - tests := []test{ - {input: "foo_bar.star", shouldErr: false}, - {input: "foo_bar", shouldErr: true}, - {input: "FooBar.star", shouldErr: true}, - {input: "foo$.star", shouldErr: true}, - {input: "", shouldErr: true}, - } - - for _, tc := range tests { - err := manifest.ValidateFileName(tc.input) - - if tc.shouldErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - } - -} - -func TestValidatePackageName(t *testing.T) { - type test struct { - input string - shouldErr bool - } - - tests := []test{ - {input: "foobar", shouldErr: false}, - {input: "foo_bar", shouldErr: true}, - {input: "FooBar", shouldErr: true}, - {input: "foo$", shouldErr: true}, - {input: "", shouldErr: true}, - } - - for _, tc := range tests { - err := manifest.ValidatePackageName(tc.input) - - if tc.shouldErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - } - -} diff --git a/runtime/applet.go b/runtime/applet.go index c515515f69..c97995d07a 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" "io/fs" - "path/filepath" + "path" "slices" "strings" "testing" @@ -56,6 +56,7 @@ type Applet struct { loader ModuleLoader initializers []ThreadInitializer + loadedPaths map[string]bool globals map[string]starlark.StringDict @@ -119,8 +120,9 @@ func NewApplet(id string, src []byte, opts ...AppletOption) (*Applet, error) { func NewAppletFromFS(id string, fsys fs.FS, opts ...AppletOption) (*Applet, error) { a := &Applet{ - ID: id, - globals: make(map[string]starlark.StringDict), + ID: id, + globals: make(map[string]starlark.StringDict), + loadedPaths: make(map[string]bool), } for _, opt := range opts { @@ -274,6 +276,7 @@ func (a *Applet) Call(ctx context.Context, callable *starlark.Function, args ... }() t := a.newThread(ctx) + defer starlarkutil.RunOnExitFuncs(t) context.AfterFunc(ctx, func() { t.Cancel(context.Cause(ctx).Error()) @@ -296,23 +299,33 @@ func (a *Applet) Call(ctx context.Context, callable *starlark.Function, args ... return resultVal, nil } +// PathsForBundle returns a list of all the paths that have been loaded by the +// applet. This is useful for creating a bundle of the applet. +func (a *Applet) PathsForBundle() []string { + paths := make([]string, 0, len(a.loadedPaths)) + for path := range a.loadedPaths { + paths = append(paths, path) + } + return paths +} + func (a *Applet) load(fsys fs.FS) (err error) { - if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, walkDirErr error) error { + if err := fs.WalkDir(fsys, ".", func(pathToLoad string, d fs.DirEntry, walkDirErr error) error { if walkDirErr != nil { return walkDirErr } - if d.IsDir() || filepath.Dir(path) != "." { + if d.IsDir() || path.Dir(pathToLoad) != "." { // only process files in the root directory return nil } - if !strings.HasSuffix(path, ".star") { + if !strings.HasSuffix(pathToLoad, ".star") { // not a starlark file return nil } - return a.ensureLoaded(fsys, path) + return a.ensureLoaded(fsys, pathToLoad) }); err != nil { return err } @@ -324,7 +337,7 @@ func (a *Applet) load(fsys fs.FS) (err error) { return nil } -func (a *Applet) ensureLoaded(fsys fs.FS, path string, currentlyLoading ...string) (err error) { +func (a *Applet) ensureLoaded(fsys fs.FS, pathToLoad string, currentlyLoading ...string) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("panic while executing %s: %v", a.ID, r) @@ -332,24 +345,28 @@ func (a *Applet) ensureLoaded(fsys fs.FS, path string, currentlyLoading ...strin }() // normalize path so that it can be used as a key - path = filepath.Clean(path) - if _, ok := a.globals[path]; ok { + pathToLoad = path.Clean(pathToLoad) + if _, ok := a.globals[pathToLoad]; ok { // already loaded, good to go return nil } // use the currentlyLoading slice to detect circular dependencies - if slices.Contains(currentlyLoading, path) { - return fmt.Errorf("circular dependency detected: %s -> %s", strings.Join(currentlyLoading, " -> "), path) + if slices.Contains(currentlyLoading, pathToLoad) { + return fmt.Errorf("circular dependency detected: %s -> %s", strings.Join(currentlyLoading, " -> "), pathToLoad) } else { // mark this file as currently loading. if we encounter it again, // we have a circular dependency. - currentlyLoading = append(currentlyLoading, path) + currentlyLoading = append(currentlyLoading, pathToLoad) + + // also mark the file as loaded to keep track of all of the files + // that have been loaded + a.loadedPaths[pathToLoad] = true } - src, err := fs.ReadFile(fsys, path) + src, err := fs.ReadFile(fsys, pathToLoad) if err != nil { - return fmt.Errorf("reading %s: %v", path, err) + return fmt.Errorf("reading %s: %v", pathToLoad, err) } predeclared := starlark.StringDict{ @@ -357,11 +374,12 @@ func (a *Applet) ensureLoaded(fsys fs.FS, path string, currentlyLoading ...strin } thread := a.newThread(context.Background()) + defer starlarkutil.RunOnExitFuncs(thread) // override loader to allow loading starlark files thread.Load = func(thread *starlark.Thread, module string) (starlark.StringDict, error) { // normalize module path - modulePath := filepath.Clean(module) + modulePath := path.Clean(module) // if the module exists on the filesystem, load it if _, err := fs.Stat(fsys, modulePath); err == nil { @@ -382,53 +400,64 @@ func (a *Applet) ensureLoaded(fsys fs.FS, path string, currentlyLoading ...strin return a.loadModule(thread, module) } - globals, err := starlark.ExecFileOptions( - &syntax.FileOptions{ - Set: true, - Recursion: true, - }, - thread, - a.ID, - src, - predeclared, - ) - if err != nil { - return fmt.Errorf("starlark.ExecFile: %v", err) - } - a.globals[path] = globals - - // if the file is in the root directory, check for the main function - // and schema function - mainFun, _ := globals["main"].(*starlark.Function) - if mainFun != nil { - if a.mainFile != "" { - return fmt.Errorf("multiple files with a main() function:\n- %s\n- %s", path, a.mainFile) + switch path.Ext(pathToLoad) { + case ".star": + globals, err := starlark.ExecFileOptions( + &syntax.FileOptions{ + Set: true, + Recursion: true, + }, + thread, + a.ID, + src, + predeclared, + ) + if err != nil { + return fmt.Errorf("starlark.ExecFile: %v", err) } + a.globals[pathToLoad] = globals + + // if the file is in the root directory, check for the main function + // and schema function + mainFun, _ := globals["main"].(*starlark.Function) + if mainFun != nil { + if a.mainFile != "" { + return fmt.Errorf("multiple files with a main() function:\n- %s\n- %s", pathToLoad, a.mainFile) + } - a.mainFile = path - a.mainFun = mainFun - } - - schemaFun, _ := globals[schema.SchemaFunctionName].(*starlark.Function) - if schemaFun != nil { - if a.schemaFile != "" { - return fmt.Errorf("multiple files with a %s() function:\n- %s\n- %s", schema.SchemaFunctionName, path, a.schemaFile) + a.mainFile = pathToLoad + a.mainFun = mainFun } - a.schemaFile = path - schemaVal, err := a.Call(context.Background(), schemaFun) - if err != nil { - return fmt.Errorf("calling schema function for %s: %w", a.ID, err) - } + schemaFun, _ := globals[schema.SchemaFunctionName].(*starlark.Function) + if schemaFun != nil { + if a.schemaFile != "" { + return fmt.Errorf("multiple files with a %s() function:\n- %s\n- %s", schema.SchemaFunctionName, pathToLoad, a.schemaFile) + } + a.schemaFile = pathToLoad - a.schema, err = schema.FromStarlark(schemaVal, globals) - if err != nil { - return fmt.Errorf("parsing schema for %s: %w", a.ID, err) + schemaVal, err := a.Call(context.Background(), schemaFun) + if err != nil { + return fmt.Errorf("calling schema function for %s: %w", a.ID, err) + } + + a.schema, err = schema.FromStarlark(schemaVal, globals) + if err != nil { + return fmt.Errorf("parsing schema for %s: %w", a.ID, err) + } + + a.schemaJSON, err = json.Marshal(a.schema) + if err != nil { + return fmt.Errorf("serializing schema to JSON for %s: %w", a.ID, err) + } } - a.schemaJSON, err = json.Marshal(a.schema) - if err != nil { - return fmt.Errorf("serializing schema to JSON for %s: %w", a.ID, err) + default: + a.globals[pathToLoad] = starlark.StringDict{ + "file": File{ + fsys: fsys, + path: pathToLoad, + }.Struct(), } } diff --git a/runtime/file.go b/runtime/file.go new file mode 100644 index 0000000000..c06a1115b3 --- /dev/null +++ b/runtime/file.go @@ -0,0 +1,112 @@ +package runtime + +import ( + "fmt" + "io" + "io/fs" + + "go.starlark.net/starlark" + "go.starlark.net/starlarkstruct" +) + +type File struct { + fsys fs.FS + path string +} + +func (f File) Struct() *starlarkstruct.Struct { + return starlarkstruct.FromStringDict(starlark.String("File"), starlark.StringDict{ + "path": starlark.String(f.path), + "readall": starlark.NewBuiltin("readall", f.readall), + }) +} + +func (f File) readall(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + var mode starlark.String + if err := starlark.UnpackArgs("readall", args, kwargs, "mode?", &mode); err != nil { + return nil, err + } + + r, err := f.reader(string(mode)) + if err != nil { + return nil, err + } + defer r.Close() + + return r.read(thread, nil, nil, nil) +} + +func (f File) reader(mode string) (*Reader, error) { + var binaryMode bool + switch mode { + case "", "r", "rt": + binaryMode = false + + case "rb": + binaryMode = true + + default: + return nil, fmt.Errorf("unsupported mode: %s", mode) + } + + fl, err := f.fsys.Open(f.path) + if err != nil { + return nil, err + } + return &Reader{fl, binaryMode}, nil +} + +type Reader struct { + io.ReadCloser + binaryMode bool +} + +func (r Reader) Struct() *starlarkstruct.Struct { + return starlarkstruct.FromStringDict(starlark.String("Reader"), starlark.StringDict{ + "read": starlark.NewBuiltin("read", r.read), + "close": starlark.NewBuiltin("close", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + return nil, r.Close() + }), + }) +} + +// read reads the contents of the file. The Starlark signature is: +// +// read(size=-1) -> bytes +func (r Reader) read(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + starlarkSize := starlark.MakeInt(-1) + if err := starlark.UnpackArgs("read", args, kwargs, "size?", &starlarkSize); err != nil { + return nil, err + } + + var size int + if err := starlark.AsInt(starlarkSize, &size); err != nil { + return nil, fmt.Errorf("size is not an int") + } + + returnType := func(buf []byte) starlark.Value { + if r.binaryMode { + return starlark.Bytes(buf) + } else { + return starlark.String(buf) + } + } + + if size < 0 { + // read and return all bytes + buf, err := io.ReadAll(r) + if err != nil { + return nil, err + } + + return returnType(buf), nil + } else { + // read and return size bytes + buf := make([]byte, size) + _, err := r.Read(buf) + if err != nil { + return nil, err + } + return returnType(buf), nil + } +} diff --git a/runtime/file_test.go b/runtime/file_test.go new file mode 100644 index 0000000000..4bd2bb6d1e --- /dev/null +++ b/runtime/file_test.go @@ -0,0 +1,39 @@ +package runtime + +import ( + "testing" + "testing/fstest" + + "github.com/stretchr/testify/require" +) + +func TestReadFile(t *testing.T) { + src := ` +load("hello.txt", hello = "file") + +def assert_eq(message, actual, expected): + if not expected == actual: + fail(message, "-", "expected", expected, "actual", actual) + +def test_readall(): + assert_eq("readall", hello.readall(), "hello world") + +def test_readall_binary(): + assert_eq("readall_binary", hello.readall("rb"), b"hello world") + +def main(): + pass + +` + + helloTxt := `hello world` + + vfs := &fstest.MapFS{ + "main.star": {Data: []byte(src)}, + "hello.txt": {Data: []byte(helloTxt)}, + } + + app, err := NewAppletFromFS("test_read_file", vfs) + require.NoError(t, err) + app.RunTests(t) +} diff --git a/server/loader/loader.go b/server/loader/loader.go index 32ae9322b1..103a157e45 100644 --- a/server/loader/loader.go +++ b/server/loader/loader.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io/fs" "log" "time" @@ -18,7 +19,7 @@ import ( // Loader is a structure to provide applet loading when a file changes or on // demand. type Loader struct { - filename string + fs fs.FS fileChanges chan bool watch bool applet runtime.Applet @@ -42,7 +43,7 @@ type Update struct { // encoded WebP strings. If watch is enabled, both file changes and on demand // requests will send updates over the updatesChan. func NewLoader( - filename string, + fs fs.FS, watch bool, fileChanges chan bool, updatesChan chan Update, @@ -51,7 +52,7 @@ func NewLoader( ) (*Loader, error) { l := &Loader{ - filename: filename, + fs: fs, fileChanges: fileChanges, watch: watch, applet: runtime.Applet{}, @@ -69,7 +70,7 @@ func NewLoader( runtime.InitCache(cache) if !l.watch { - app, err := loadScript("app-id", l.filename) + app, err := loadScript("app-id", l.fs) l.markInitialLoadComplete() if err != nil { return nil, err @@ -106,7 +107,7 @@ func (l *Loader) Run() error { l.updatesChan <- up l.resultsChan <- up case <-l.fileChanges: - log.Printf("detected updates for %s, reloading\n", l.filename) + log.Println("detected updates, reloading") up := Update{} webp, err := l.loadApplet(config) @@ -156,7 +157,7 @@ func (l *Loader) CallSchemaHandler(ctx context.Context, handlerName, parameter s func (l *Loader) loadApplet(config map[string]string) (string, error) { if l.watch { - app, err := loadScript("app-id", l.filename) + app, err := loadScript("app-id", l.fs) l.markInitialLoadComplete() if err != nil { return "", err diff --git a/server/loader/script.go b/server/loader/script.go index 4a27f3ff97..88cc74b42f 100644 --- a/server/loader/script.go +++ b/server/loader/script.go @@ -1,19 +1,11 @@ -//go:build !js && !wasm - package loader import ( - "fmt" - "os" + "io/fs" "tidbyt.dev/pixlet/runtime" ) -func loadScript(appID string, filename string) (*runtime.Applet, error) { - src, err := os.ReadFile(filename) - if err != nil { - return nil, fmt.Errorf("failed to read file %s: %w", filename, err) - } - - return runtime.NewApplet(appID, src) +func loadScript(appID string, fs fs.FS) (*runtime.Applet, error) { + return runtime.NewAppletFromFS(appID, fs) } diff --git a/server/loader/script_js.go b/server/loader/script_js.go deleted file mode 100644 index c07b9b4fa1..0000000000 --- a/server/loader/script_js.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build js && wasm - -package loader - -import ( - "fmt" - "io" - "net/http" - - "tidbyt.dev/pixlet/runtime" -) - -func loadScript(appID string, filename string) (*runtime.Applet, error) { - res, err := http.Get(filename) - if err != nil { - return nil, fmt.Errorf("failed to fetch file %s: %w", filename, err) - } - defer res.Body.Close() - - src, err := io.ReadAll(res.Body) - if err != nil { - return nil, fmt.Errorf("failed to read file %s: %w", filename, err) - } - - return runtime.NewApplet(appID, src) -} diff --git a/server/server.go b/server/server.go index 165228775f..6ff5459674 100644 --- a/server/server.go +++ b/server/server.go @@ -2,35 +2,58 @@ package server import ( "fmt" + "io/fs" + "os" + "path/filepath" + "strings" "golang.org/x/sync/errgroup" "tidbyt.dev/pixlet/server/browser" "tidbyt.dev/pixlet/server/loader" - "tidbyt.dev/pixlet/server/watcher" + "tidbyt.dev/pixlet/tools" ) // Server provides functionality to serve Starlark over HTTP. It has // functionality to watch a file and hot reload the browser on changes. type Server struct { - watcher *watcher.Watcher + watcher *Watcher browser *browser.Browser loader *loader.Loader watch bool } // NewServer creates a new server initialized with the applet. -func NewServer(host string, port int, watch bool, filename string, maxDuration int, timeout int) (*Server, error) { +func NewServer(host string, port int, watch bool, path string, maxDuration int, timeout int) (*Server, error) { fileChanges := make(chan bool, 100) - w := watcher.NewWatcher(filename, fileChanges) + + // check if path exists, and whether it is a directory or a file + info, err := os.Stat(path) + if err != nil { + return nil, fmt.Errorf("failed to stat %s: %w", path, err) + } + + var fs fs.FS + var w *Watcher + if info.IsDir() { + fs = os.DirFS(path) + w = NewWatcher(path, fileChanges) + } else { + if !strings.HasSuffix(path, ".star") { + return nil, fmt.Errorf("script file must have suffix .star: %s", path) + } + + fs = tools.NewSingleFileFS(path) + w = NewWatcher(filepath.Dir(path), fileChanges) + } updatesChan := make(chan loader.Update, 100) - l, err := loader.NewLoader(filename, watch, fileChanges, updatesChan, maxDuration, timeout) + l, err := loader.NewLoader(fs, watch, fileChanges, updatesChan, maxDuration, timeout) if err != nil { return nil, err } addr := fmt.Sprintf("%s:%d", host, port) - b, err := browser.NewBrowser(addr, filename, watch, updatesChan, l) + b, err := browser.NewBrowser(addr, filepath.Base(path), watch, updatesChan, l) if err != nil { return nil, err } diff --git a/server/watcher/fs.go b/server/watcher.go similarity index 63% rename from server/watcher/fs.go rename to server/watcher.go index d7dec016c5..de50bbdb73 100644 --- a/server/watcher/fs.go +++ b/server/watcher.go @@ -1,14 +1,29 @@ -//go:build !js && !wasm - -package watcher +package server import ( "fmt" + "log" "path/filepath" + "strings" "github.com/fsnotify/fsnotify" ) +// Watcher is a structure to watch a file for changes and notify a channel. +type Watcher struct { + path string + fileChanges chan bool +} + +// NewWatcher instantiates a new watcher with the provided filename and changes +// channel. +func NewWatcher(filename string, fileChanges chan bool) *Watcher { + return &Watcher{ + path: filepath.FromSlash(filename), + fileChanges: fileChanges, + } +} + // Run starts the file watcher in a blocking fashion. This watches an entire // directory and only notifies the channel when the specified file is changed. // If there is an error, it's returned. It's up to the caller to respawn the @@ -27,7 +42,7 @@ func (w *Watcher) Run() error { } defer watcher.Close() - watcher.Add(filepath.Dir(w.filename)) + watcher.Add(w.path) for { select { @@ -35,7 +50,8 @@ func (w *Watcher) Run() error { if !ok { return fmt.Errorf("something is weird with the file watcher") } - if event.Name == w.filename && (event.Op&(fsnotify.Write|fsnotify.Create)) != 0 { + log.Println(event.Name) + if strings.HasPrefix(event.Name, w.path) && shouldNotify(event.Op) { w.fileChanges <- true } @@ -47,3 +63,9 @@ func (w *Watcher) Run() error { } } } + +func shouldNotify(op fsnotify.Op) bool { + // notify on all ops except for chmod, since that is discouraged + // in the fsnotify docs. + return op.Has(fsnotify.Write | fsnotify.Create | fsnotify.Remove | fsnotify.Rename) +} diff --git a/server/watcher/fs_js.go b/server/watcher/fs_js.go deleted file mode 100644 index 639c6caaa2..0000000000 --- a/server/watcher/fs_js.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build js && wasm - -package watcher - -import ( - "fmt" -) - -func (w *Watcher) Run() error { - return fmt.Errorf("file watching not supported in WASM") -} diff --git a/server/watcher/watcher.go b/server/watcher/watcher.go deleted file mode 100644 index 0090c41862..0000000000 --- a/server/watcher/watcher.go +++ /dev/null @@ -1,21 +0,0 @@ -// Package watcher provides a simple mechanism to watch a file for changes. -package watcher - -import ( - "path/filepath" -) - -// Watcher is a structure to watch a file for changes and notify a channel. -type Watcher struct { - filename string - fileChanges chan bool -} - -// NewWatcher instantiates a new watcher with the provided filename and changes -// channel. -func NewWatcher(filename string, fileChanges chan bool) *Watcher { - return &Watcher{ - filename: filepath.FromSlash(filename), - fileChanges: fileChanges, - } -} diff --git a/starlarkutil/onexit.go b/starlarkutil/onexit.go new file mode 100644 index 0000000000..d3ee2a6cdc --- /dev/null +++ b/starlarkutil/onexit.go @@ -0,0 +1,27 @@ +package starlarkutil + +import "go.starlark.net/starlark" + +const ( + // ThreadOnExitKey is the key used to store functions that should be called + // when a thread exits. + ThreadOnExitKey = "tidbyt.dev/pixlet/runtime/on_exit" +) + +type threadOnExitFunc func() + +func AddOnExit(thread *starlark.Thread, fn threadOnExitFunc) { + if onExit, ok := thread.Local(ThreadOnExitKey).(*[]threadOnExitFunc); ok { + *onExit = append(*onExit, fn) + } else { + thread.SetLocal(ThreadOnExitKey, &[]threadOnExitFunc{fn}) + } +} + +func RunOnExitFuncs(thread *starlark.Thread) { + if onExit, ok := thread.Local(ThreadOnExitKey).(*[]threadOnExitFunc); ok { + for _, fn := range *onExit { + fn() + } + } +} diff --git a/tools/generator/generator.go b/tools/generator/generator.go index 132e41a3d3..39c3a3add6 100644 --- a/tools/generator/generator.go +++ b/tools/generator/generator.go @@ -83,12 +83,12 @@ func (g *Generator) RemoveApp(app *manifest.Manifest) error { } func (g *Generator) createDir(app *manifest.Manifest) error { - p := path.Join(g.root, appsDir, app.PackageName) + p := path.Join(g.root, appsDir, manifest.GenerateDirName(app.Name)) return os.MkdirAll(p, os.ModePerm) } func (g *Generator) removeDir(app *manifest.Manifest) error { - p := path.Join(g.root, appsDir, app.PackageName) + p := path.Join(g.root, appsDir, manifest.GenerateDirName(app.Name)) return os.RemoveAll(p) } @@ -96,7 +96,7 @@ func (g *Generator) writeManifest(app *manifest.Manifest) error { var p string switch g.appType { case Community, Internal: - p = path.Join(g.root, appsDir, app.PackageName, manifestName) + p = path.Join(g.root, appsDir, manifest.GenerateDirName(app.Name), manifestName) default: p = path.Join(g.root, manifestName) } @@ -111,12 +111,15 @@ func (g *Generator) writeManifest(app *manifest.Manifest) error { } func (g *Generator) generateStarlark(app *manifest.Manifest) (string, error) { + dir := manifest.GenerateDirName(app.Name) + fn := manifest.GenerateFileName(app.Name) + var p string switch g.appType { case Community, Internal: - p = path.Join(g.root, appsDir, app.PackageName, app.FileName) + p = path.Join(g.root, appsDir, dir, fn) default: - p = path.Join(g.root, app.FileName) + p = path.Join(g.root, fn) } file, err := os.Create(p) diff --git a/tools/singlefilefs.go b/tools/singlefilefs.go new file mode 100644 index 0000000000..87ab8e1f19 --- /dev/null +++ b/tools/singlefilefs.go @@ -0,0 +1,27 @@ +package tools + +import ( + "io/fs" + "os" + "path/filepath" +) + +type SingleFileFS struct { + Path string + baseFS fs.FS +} + +func NewSingleFileFS(filePath string) *SingleFileFS { + return &SingleFileFS{ + Path: filePath, + baseFS: os.DirFS(filepath.Dir(filePath)), + } +} + +func (sfs *SingleFileFS) Open(name string) (fs.File, error) { + if name != "." && name != filepath.Base(sfs.Path) { + return nil, fs.ErrNotExist + } + + return sfs.baseFS.Open(name) +} From 648ba9811fb47977cf885d3ee1064476bf7e7654 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Wed, 24 Apr 2024 12:53:10 -0400 Subject: [PATCH 17/19] Clean up bundle API for loading bundles (#1049) This is mostly important for embedders like the Tidbyt backend. --- bundle/bundle.go | 10 +++++----- bundle/bundle_test.go | 2 +- cmd/private/bundle.go | 2 +- cmd/private/upload.go | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bundle/bundle.go b/bundle/bundle.go index fe777de1ee..74454b8344 100644 --- a/bundle/bundle.go +++ b/bundle/bundle.go @@ -34,7 +34,7 @@ type AppBundle struct { Source fs.FS } -func fromFS(fs fs.FS) (*AppBundle, error) { +func FromFS(fs fs.FS) (*AppBundle, error) { m, err := fs.Open(manifest.ManifestFileName) if err != nil { return nil, fmt.Errorf("could not open manifest: %w", err) @@ -53,10 +53,10 @@ func fromFS(fs fs.FS) (*AppBundle, error) { }, nil } -// InitFromPath translates a directory containing an app manifest and source +// FromDir translates a directory containing an app manifest and source // into an AppBundle. -func InitFromPath(dir string) (*AppBundle, error) { - return fromFS(os.DirFS(dir)) +func FromDir(dir string) (*AppBundle, error) { + return FromFS(os.DirFS(dir)) } // LoadBundle loads a compressed archive into an AppBundle. @@ -78,7 +78,7 @@ func LoadBundle(in io.Reader) (*AppBundle, error) { return nil, fmt.Errorf("creating tarfs: %w", err) } - return fromFS(fs) + return FromFS(fs) } // WriteBundleToPath is a helper to be able to write the bundle to a provided diff --git a/bundle/bundle_test.go b/bundle/bundle_test.go index 307a0eb6b1..0f6a28059e 100644 --- a/bundle/bundle_test.go +++ b/bundle/bundle_test.go @@ -11,7 +11,7 @@ import ( func TestBundleWriteAndLoad(t *testing.T) { // Ensure we can load the bundle from an app. - ab, err := bundle.InitFromPath("testdata/testapp") + ab, err := bundle.FromDir("testdata/testapp") assert.NoError(t, err) assert.Equal(t, "test-app", ab.Manifest.ID) assert.NotNil(t, ab.Source) diff --git a/cmd/private/bundle.go b/cmd/private/bundle.go index 7bdc1c6338..634e35e747 100644 --- a/cmd/private/bundle.go +++ b/cmd/private/bundle.go @@ -42,7 +42,7 @@ be a gzip compressed tar file that can be uploaded to Tidbyt for deployment.`, return fmt.Errorf("output must be a directory") } - ab, err := bundle.InitFromPath(bundleInput) + ab, err := bundle.FromDir(bundleInput) if err != nil { return fmt.Errorf("could not init bundle: %w", err) } diff --git a/cmd/private/upload.go b/cmd/private/upload.go index 7a52df06a8..72f68cbc7d 100644 --- a/cmd/private/upload.go +++ b/cmd/private/upload.go @@ -63,7 +63,7 @@ flags.`, // Create bundle buf := &bytes.Buffer{} - ab, err := bundle.InitFromPath(uploadDir) + ab, err := bundle.FromDir(uploadDir) if err != nil { return fmt.Errorf("could not init bundle: %w", err) } From 9ebdaacc9275f47100804b27ecc5ac2d9bcb34c8 Mon Sep 17 00:00:00 2001 From: Tom Curtis <105217023+dinosaursrarr@users.noreply.github.com> Date: Wed, 24 Apr 2024 19:53:11 +0100 Subject: [PATCH 18/19] Add bsoup module (#853) Responding to request on forum: https://discuss.tidbyt.com/t/beautiful-soup-python-supported/5328/2 I can imagine you saying no, because this provides similar functionality to the existing html module. But I agree with the poster that this is a better API and I would prefer to be able to use it. --- docs/modules.md | 1 + go.mod | 1 + go.sum | 1 + runtime/applet.go | 4 ++++ runtime/applet_test.go | 3 +++ 5 files changed, 10 insertions(+) diff --git a/docs/modules.md b/docs/modules.md index a7d05446fd..9aad04657d 100644 --- a/docs/modules.md +++ b/docs/modules.md @@ -28,6 +28,7 @@ individual modules, please refer to the Starlib documentation. | Module | Description | | --- | --- | +| [`bsoup.star`](https://github.com/qri-io/starlib/blob/master/bsoup) | Beautiful Soup-like functions for HTML | | [`compress/gzip.star`](https://github.com/qri-io/starlib/blob/master/compress/gzip) | gzip decompressing | | [`compress/zipfile.star`](https://github.com/qri-io/starlib/blob/master/zipfile) | zip decompressing | | [`encoding/base64.star`](https://github.com/qri-io/starlib/tree/master/encoding/base64) | Base 64 encoding and decoding | diff --git a/go.mod b/go.mod index 485b35137f..38925cfdb2 100644 --- a/go.mod +++ b/go.mod @@ -60,6 +60,7 @@ require ( github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect diff --git a/go.sum b/go.sum index af16291738..0bc7726ec4 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e h1:44fmjqDtdCiUNlSjJVp+w1AOs6na3Y6Ai0aIeseFjkI= github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= diff --git a/runtime/applet.go b/runtime/applet.go index c97995d07a..45f98e74e6 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -13,6 +13,7 @@ import ( 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" @@ -510,6 +511,9 @@ func (a *Applet) loadModule(thread *starlark.Thread, module string) (starlark.St case "xpath.star": return xpath.LoadXPathModule() + case "bsoup.star": + return starlibbsoup.LoadModule() + case "compress/gzip.star": return starlark.StringDict{ starlibgzip.Module.Name: starlibgzip.Module, diff --git a/runtime/applet_test.go b/runtime/applet_test.go index 6ba07d8af6..bcb121f99a 100644 --- a/runtime/applet_test.go +++ b/runtime/applet_test.go @@ -221,6 +221,7 @@ func TestModuleLoading(t *testing.T) { // Our basic set of modules can be imported src := ` load("render.star", "render") +load("bsoup.star", "bsoup") load("encoding/base64.star", "base64") load("encoding/json.star", "json") load("http.star", "http") @@ -245,6 +246,8 @@ def main(): fail("re broken") if time.parse_duration("10s").seconds != 10: fail("time broken") + if bsoup.parseHtml("

foo

").find("h1").get_text() != "foo": + fail("bsoup broken") return render.Root(child=render.Box()) ` app, err := NewApplet("test.star", []byte(src)) From 0ad59b9f01f462c4cdb87723a27f193eb682d3fc Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Wed, 24 Apr 2024 15:17:05 -0400 Subject: [PATCH 19/19] Provide file name in load errors (#1050) When loading a Starlark file fails with an error, provide the name of the file. Since apps can now contain multiple files, this is necessary for the error message to make sense. --- runtime/applet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/applet.go b/runtime/applet.go index 45f98e74e6..2bac67fe01 100644 --- a/runtime/applet.go +++ b/runtime/applet.go @@ -409,7 +409,7 @@ func (a *Applet) ensureLoaded(fsys fs.FS, pathToLoad string, currentlyLoading .. Recursion: true, }, thread, - a.ID, + path.Join(a.ID, pathToLoad), src, predeclared, )