From ef7053bb0e9ce4998c11ce2fd571cff7334486e9 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Thu, 18 Dec 2025 16:10:29 +0000 Subject: [PATCH] refactor(vfox): remove submodules, embed plugins directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove git submodules for 18 vfox plugins - Embed plugin Lua files directly in the repository - Simplify release-plz to delete and re-clone plugins (like aqua-registry) - Remove `submodules: true` from all GitHub Actions workflows - Rename mise-semver to vfox-semver in registry Benefits: - No more `git submodule update --init --recursive` needed - Simpler CI/CD without submodule checkout - All code visible directly in repo - Cleaner git history for plugin updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/autofix.yml | 2 - .github/workflows/hyperfine.yml | 1 - .github/workflows/ppa-publish.yml | 1 - .github/workflows/registry.yml | 2 - .github/workflows/release-fig.yml | 1 - .github/workflows/release-plz.yml | 1 - .github/workflows/release.yml | 6 - .github/workflows/test-vfox.yml | 2 - .github/workflows/test.yml | 13 -- .gitmodules | 54 -------- crates/vfox/embedded-plugins/mise-semver | 1 - crates/vfox/embedded-plugins/vfox-1password | 1 - .../vfox-1password/hooks/available.lua | 122 ++++++++++++++++++ .../vfox-1password/hooks/env_keys.lua | 12 ++ .../vfox-1password/hooks/pre_install.lua | 52 ++++++++ .../vfox-1password/metadata.lua | 20 +++ crates/vfox/embedded-plugins/vfox-aapt2 | 1 - .../vfox-aapt2/hooks/available.lua | 14 ++ .../vfox-aapt2/hooks/env_keys.lua | 13 ++ .../vfox-aapt2/hooks/post_install.lua | 57 ++++++++ .../vfox-aapt2/hooks/pre_install.lua | 14 ++ .../embedded-plugins/vfox-aapt2/lib/util.lua | 72 +++++++++++ .../embedded-plugins/vfox-aapt2/metadata.lua | 20 +++ crates/vfox/embedded-plugins/vfox-ag | 1 - .../vfox-ag/hooks/available.lua | 55 ++++++++ .../vfox-ag/hooks/env_keys.lua | 14 ++ .../vfox-ag/hooks/post_install.lua | 31 +++++ .../vfox-ag/hooks/pre_install.lua | 18 +++ .../embedded-plugins/vfox-ag/metadata.lua | 26 ++++ crates/vfox/embedded-plugins/vfox-android-sdk | 1 - .../vfox-android-sdk/hooks/available.lua | 39 ++++++ .../vfox-android-sdk/hooks/env_keys.lua | 29 +++++ .../vfox-android-sdk/hooks/post_install.lua | 49 +++++++ .../vfox-android-sdk/hooks/pre_install.lua | 106 +++++++++++++++ .../vfox-android-sdk/metadata.lua | 23 ++++ crates/vfox/embedded-plugins/vfox-ant | 1 - .../vfox-ant/hooks/available.lua | 14 ++ .../vfox-ant/hooks/env_keys.lua | 17 +++ .../vfox-ant/hooks/post_install.lua | 8 ++ .../vfox-ant/hooks/pre_install.lua | 40 ++++++ .../embedded-plugins/vfox-ant/lib/util.lua | 56 ++++++++ .../embedded-plugins/vfox-ant/metadata.lua | 20 +++ .../vfox/embedded-plugins/vfox-asciidoctorj | 1 - .../vfox-asciidoctorj/hooks/available.lua | 61 +++++++++ .../vfox-asciidoctorj/hooks/env_keys.lua | 13 ++ .../vfox-asciidoctorj/hooks/pre_install.lua | 23 ++++ .../vfox-asciidoctorj/metadata.lua | 21 +++ .../vfox-azure-functions-core-tools | 1 - .../hooks/available.lua | 51 ++++++++ .../hooks/env_keys.lua | 13 ++ .../hooks/post_install.lua | 24 ++++ .../hooks/pre_install.lua | 48 +++++++ .../metadata.lua | 20 +++ crates/vfox/embedded-plugins/vfox-bfs | 1 - .../vfox-bfs/hooks/available.lua | 18 +++ .../vfox-bfs/hooks/env_keys.lua | 12 ++ .../vfox-bfs/hooks/post_install.lua | 36 ++++++ .../vfox-bfs/hooks/pre_install.lua | 19 +++ .../embedded-plugins/vfox-bfs/lib/util.lua | 68 ++++++++++ .../embedded-plugins/vfox-bfs/metadata.lua | 26 ++++ crates/vfox/embedded-plugins/vfox-bpkg | 1 - .../vfox-bpkg/hooks/available.lua | 49 +++++++ .../vfox-bpkg/hooks/env_keys.lua | 14 ++ .../vfox-bpkg/hooks/post_install.lua | 73 +++++++++++ .../vfox-bpkg/hooks/pre_install.lua | 18 +++ .../embedded-plugins/vfox-bpkg/metadata.lua | 12 ++ crates/vfox/embedded-plugins/vfox-carthage | 1 - .../vfox-carthage/hooks/available.lua | 18 +++ .../vfox-carthage/hooks/env_keys.lua | 12 ++ .../vfox-carthage/hooks/post_install.lua | 70 ++++++++++ .../vfox-carthage/hooks/pre_install.lua | 18 +++ .../vfox-carthage/lib/util.lua | 68 ++++++++++ .../vfox-carthage/metadata.lua | 26 ++++ crates/vfox/embedded-plugins/vfox-chezscheme | 1 - .../vfox-chezscheme/hooks/available.lua | 41 ++++++ .../vfox-chezscheme/hooks/env_keys.lua | 12 ++ .../vfox-chezscheme/hooks/post_install.lua | 49 +++++++ .../vfox-chezscheme/hooks/pre_install.lua | 16 +++ .../vfox-chezscheme/metadata.lua | 9 ++ crates/vfox/embedded-plugins/vfox-chicken | 1 - .../vfox-chicken/hooks/available.lua | 52 ++++++++ .../vfox-chicken/hooks/env_keys.lua | 27 ++++ .../vfox-chicken/hooks/post_install.lua | 47 +++++++ .../vfox-chicken/hooks/pre_install.lua | 53 ++++++++ .../vfox-chicken/metadata.lua | 12 ++ .../vfox/embedded-plugins/vfox-chromedriver | 1 - .../vfox-chromedriver/hooks/available.lua | 40 ++++++ .../vfox-chromedriver/hooks/env_keys.lua | 14 ++ .../vfox-chromedriver/hooks/post_install.lua | 62 +++++++++ .../vfox-chromedriver/hooks/pre_install.lua | 80 ++++++++++++ .../vfox-chromedriver/metadata.lua | 11 ++ crates/vfox/embedded-plugins/vfox-clickhouse | 1 - .../vfox-clickhouse/hooks/available.lua | 18 +++ .../vfox-clickhouse/hooks/env_keys.lua | 12 ++ .../vfox-clickhouse/hooks/post_install.lua | 87 +++++++++++++ .../vfox-clickhouse/hooks/pre_install.lua | 39 ++++++ .../vfox-clickhouse/lib/util.lua | 96 ++++++++++++++ .../vfox-clickhouse/metadata.lua | 26 ++++ crates/vfox/embedded-plugins/vfox-gcloud | 1 - .../vfox-gcloud/hooks/available.lua | 102 +++++++++++++++ .../vfox-gcloud/hooks/env_keys.lua | 24 ++++ .../vfox-gcloud/hooks/post_install.lua | 80 ++++++++++++ .../vfox-gcloud/hooks/pre_install.lua | 115 +++++++++++++++++ .../embedded-plugins/vfox-gcloud/metadata.lua | 26 ++++ .../vfox-semver/hooks/available.lua | 47 +++++++ .../vfox-semver/hooks/env_keys.lua | 12 ++ .../vfox-semver/hooks/post_install.lua | 25 ++++ .../vfox-semver/hooks/pre_install.lua | 13 ++ .../embedded-plugins/vfox-semver/metadata.lua | 9 ++ crates/vfox/embedded-plugins/vfox-vlang | 1 - .../vfox-vlang/hooks/available.lua | 8 ++ .../vfox-vlang/hooks/env_keys.lua | 15 +++ .../vfox-vlang/hooks/post_install.lua | 6 + .../vfox-vlang/hooks/pre_install.lua | 18 +++ .../vfox-vlang/hooks/pre_use.lua | 6 + .../embedded-plugins/vfox-vlang/lib/util.lua | 71 ++++++++++ .../embedded-plugins/vfox-vlang/metadata.lua | 38 ++++++ crates/vfox/embedded-plugins/vfox-yarn | 1 - .../vfox-yarn/hooks/available.lua | 117 +++++++++++++++++ .../vfox-yarn/hooks/env_keys.lua | 16 +++ .../vfox-yarn/hooks/legacy_filenames.lua | 6 + .../vfox-yarn/hooks/parse_legacy_file.lua | 19 +++ .../vfox-yarn/hooks/post_install.lua | 103 +++++++++++++++ .../vfox-yarn/hooks/pre_install.lua | 40 ++++++ .../embedded-plugins/vfox-yarn/metadata.lua | 18 +++ registry.toml | 2 +- xtasks/release-plz | 72 +++-------- 127 files changed, 3529 insertions(+), 155 deletions(-) delete mode 100644 .gitmodules delete mode 160000 crates/vfox/embedded-plugins/mise-semver delete mode 160000 crates/vfox/embedded-plugins/vfox-1password create mode 100644 crates/vfox/embedded-plugins/vfox-1password/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-1password/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-1password/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-1password/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-aapt2 create mode 100644 crates/vfox/embedded-plugins/vfox-aapt2/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-aapt2/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-aapt2/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-aapt2/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-aapt2/lib/util.lua create mode 100644 crates/vfox/embedded-plugins/vfox-aapt2/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-ag create mode 100644 crates/vfox/embedded-plugins/vfox-ag/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ag/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ag/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ag/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ag/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-android-sdk create mode 100644 crates/vfox/embedded-plugins/vfox-android-sdk/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-android-sdk/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-android-sdk/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-android-sdk/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-android-sdk/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-ant create mode 100644 crates/vfox/embedded-plugins/vfox-ant/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ant/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ant/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ant/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ant/lib/util.lua create mode 100644 crates/vfox/embedded-plugins/vfox-ant/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-asciidoctorj create mode 100644 crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-asciidoctorj/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-azure-functions-core-tools create mode 100644 crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-bfs create mode 100644 crates/vfox/embedded-plugins/vfox-bfs/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bfs/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bfs/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bfs/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bfs/lib/util.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bfs/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-bpkg create mode 100644 crates/vfox/embedded-plugins/vfox-bpkg/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bpkg/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bpkg/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bpkg/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-bpkg/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-carthage create mode 100644 crates/vfox/embedded-plugins/vfox-carthage/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-carthage/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-carthage/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-carthage/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-carthage/lib/util.lua create mode 100644 crates/vfox/embedded-plugins/vfox-carthage/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-chezscheme create mode 100644 crates/vfox/embedded-plugins/vfox-chezscheme/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chezscheme/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chezscheme/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chezscheme/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chezscheme/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-chicken create mode 100644 crates/vfox/embedded-plugins/vfox-chicken/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chicken/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chicken/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chicken/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chicken/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-chromedriver create mode 100644 crates/vfox/embedded-plugins/vfox-chromedriver/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chromedriver/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chromedriver/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chromedriver/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-chromedriver/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-clickhouse create mode 100644 crates/vfox/embedded-plugins/vfox-clickhouse/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-clickhouse/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-clickhouse/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-clickhouse/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-clickhouse/lib/util.lua create mode 100644 crates/vfox/embedded-plugins/vfox-clickhouse/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-gcloud create mode 100644 crates/vfox/embedded-plugins/vfox-gcloud/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-gcloud/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-gcloud/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-gcloud/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-gcloud/metadata.lua create mode 100644 crates/vfox/embedded-plugins/vfox-semver/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-semver/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-semver/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-semver/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-semver/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-vlang create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_use.lua create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/lib/util.lua create mode 100644 crates/vfox/embedded-plugins/vfox-vlang/metadata.lua delete mode 160000 crates/vfox/embedded-plugins/vfox-yarn create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/hooks/available.lua create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/hooks/env_keys.lua create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/hooks/legacy_filenames.lua create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/hooks/parse_legacy_file.lua create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/hooks/post_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/hooks/pre_install.lua create mode 100644 crates/vfox/embedded-plugins/vfox-yarn/metadata.lua diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index e10603291d..c1d21fd672 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -28,8 +28,6 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: autofix diff --git a/.github/workflows/hyperfine.yml b/.github/workflows/hyperfine.yml index 55f0142f71..c59a0d2403 100644 --- a/.github/workflows/hyperfine.yml +++ b/.github/workflows/hyperfine.yml @@ -27,7 +27,6 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 - run: curl https://mise.run | MISE_INSTALL_PATH="$HOME/bin/mise-release" sh - run: echo "$HOME/bin" >> "$GITHUB_PATH" diff --git a/.github/workflows/ppa-publish.yml b/.github/workflows/ppa-publish.yml index 52bff84a3c..75268626c1 100644 --- a/.github/workflows/ppa-publish.yml +++ b/.github/workflows/ppa-publish.yml @@ -35,7 +35,6 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 - submodules: true - name: Set up environment variables run: | diff --git a/.github/workflows/registry.yml b/.github/workflows/registry.yml index 140be1e0e5..60e90aefdb 100644 --- a/.github/workflows/registry.yml +++ b/.github/workflows/registry.yml @@ -30,8 +30,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: build diff --git a/.github/workflows/release-fig.yml b/.github/workflows/release-fig.yml index 69d3cce461..21d576135f 100644 --- a/.github/workflows/release-fig.yml +++ b/.github/workflows/release-fig.yml @@ -14,7 +14,6 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.MISE_GH_TOKEN }} - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: build diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 87c5d55d02..05e42a507a 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -32,7 +32,6 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.MISE_GH_TOKEN }} - submodules: true - uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6 with: gpg_private_key: ${{ secrets.MISE_GPG_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 837107f477..b44ab406c6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,8 +45,6 @@ jobs: target: armv7-unknown-linux-musleabi steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - name: Install cross uses: taiki-e/install-action@0aa4f22591557b744fe31e55dbfcdfea74a073f7 # v2 with: @@ -98,8 +96,6 @@ jobs: p12-file-base64: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTS_P12 }} p12-password: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTS_P12_PASS }} - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - name: cache crates id: cache-crates uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 @@ -142,8 +138,6 @@ jobs: target: x86_64-pc-windows-msvc steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - run: rustup target add ${{matrix.target}} - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: diff --git a/.github/workflows/test-vfox.yml b/.github/workflows/test-vfox.yml index 587976de9b..8a6d99f016 100644 --- a/.github/workflows/test-vfox.yml +++ b/.github/workflows/test-vfox.yml @@ -24,8 +24,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 - run: | cargo build --all-features diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f55676a4bc..6dd7178b92 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,8 +29,6 @@ jobs: timeout-minutes: 60 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: build @@ -56,8 +54,6 @@ jobs: timeout-minutes: 60 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: build @@ -86,8 +82,6 @@ jobs: MISE_CACHE_DIR: ~/.cache/mise steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: build @@ -124,7 +118,6 @@ jobs: with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.head_ref }} - submodules: true - uses: taiki-e/install-action@0aa4f22591557b744fe31e55dbfcdfea74a073f7 # v2 with: tool: cargo-deny,cargo-msrv,cargo-machete @@ -163,7 +156,6 @@ jobs: with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.head_ref }} - submodules: true - run: rustup default nightly - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: @@ -194,7 +186,6 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 - submodules: true - name: Install build and test dependencies run: | sudo apt-get update @@ -244,8 +235,6 @@ jobs: MISE_CACHE_DIR: ~/.cache/mise steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2 with: shared-key: unit @@ -265,8 +254,6 @@ jobs: MISE_CACHE_DIR: ~/.cache/mise steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - submodules: true - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: mise-windows-latest diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a745239485..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,54 +0,0 @@ -[submodule "crates/vfox/embedded-plugins/vfox-aapt2"] - path = crates/vfox/embedded-plugins/vfox-aapt2 - url = https://github.com/mise-plugins/vfox-aapt2.git -[submodule "crates/vfox/embedded-plugins/vfox-ag"] - path = crates/vfox/embedded-plugins/vfox-ag - url = https://github.com/mise-plugins/vfox-ag.git -[submodule "crates/vfox/embedded-plugins/vfox-android-sdk"] - path = crates/vfox/embedded-plugins/vfox-android-sdk - url = https://github.com/mise-plugins/vfox-android-sdk.git -[submodule "crates/vfox/embedded-plugins/vfox-ant"] - path = crates/vfox/embedded-plugins/vfox-ant - url = https://github.com/mise-plugins/vfox-ant.git -[submodule "crates/vfox/embedded-plugins/vfox-bfs"] - path = crates/vfox/embedded-plugins/vfox-bfs - url = https://github.com/mise-plugins/vfox-bfs.git -[submodule "crates/vfox/embedded-plugins/vfox-bpkg"] - path = crates/vfox/embedded-plugins/vfox-bpkg - url = https://github.com/mise-plugins/vfox-bpkg.git -[submodule "crates/vfox/embedded-plugins/vfox-chicken"] - path = crates/vfox/embedded-plugins/vfox-chicken - url = https://github.com/mise-plugins/vfox-chicken.git -[submodule "crates/vfox/embedded-plugins/vfox-vlang"] - path = crates/vfox/embedded-plugins/vfox-vlang - url = https://github.com/mise-plugins/vfox-vlang.git -[submodule "crates/vfox/embedded-plugins/mise-semver"] - path = crates/vfox/embedded-plugins/mise-semver - url = https://github.com/mise-plugins/mise-semver.git -[submodule "crates/vfox/embedded-plugins/vfox-1password"] - path = crates/vfox/embedded-plugins/vfox-1password - url = https://github.com/mise-plugins/vfox-1password.git -[submodule "crates/vfox/embedded-plugins/vfox-asciidoctorj"] - path = crates/vfox/embedded-plugins/vfox-asciidoctorj - url = https://github.com/mise-plugins/vfox-asciidoctorj.git -[submodule "crates/vfox/embedded-plugins/vfox-azure-functions-core-tools"] - path = crates/vfox/embedded-plugins/vfox-azure-functions-core-tools - url = https://github.com/mise-plugins/vfox-azure-functions-core-tools.git -[submodule "crates/vfox/embedded-plugins/vfox-carthage"] - path = crates/vfox/embedded-plugins/vfox-carthage - url = https://github.com/mise-plugins/vfox-carthage.git -[submodule "crates/vfox/embedded-plugins/vfox-chezscheme"] - path = crates/vfox/embedded-plugins/vfox-chezscheme - url = https://github.com/mise-plugins/vfox-chezscheme.git -[submodule "crates/vfox/embedded-plugins/vfox-chromedriver"] - path = crates/vfox/embedded-plugins/vfox-chromedriver - url = https://github.com/mise-plugins/vfox-chromedriver.git -[submodule "crates/vfox/embedded-plugins/vfox-clickhouse"] - path = crates/vfox/embedded-plugins/vfox-clickhouse - url = https://github.com/mise-plugins/vfox-clickhouse.git -[submodule "crates/vfox/embedded-plugins/vfox-gcloud"] - path = crates/vfox/embedded-plugins/vfox-gcloud - url = https://github.com/mise-plugins/vfox-gcloud.git -[submodule "crates/vfox/embedded-plugins/vfox-yarn"] - path = crates/vfox/embedded-plugins/vfox-yarn - url = https://github.com/mise-plugins/vfox-yarn.git diff --git a/crates/vfox/embedded-plugins/mise-semver b/crates/vfox/embedded-plugins/mise-semver deleted file mode 160000 index d20d84b756..0000000000 --- a/crates/vfox/embedded-plugins/mise-semver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d20d84b7561438571fc23c137f8905c7abe2944c diff --git a/crates/vfox/embedded-plugins/vfox-1password b/crates/vfox/embedded-plugins/vfox-1password deleted file mode 160000 index ac765040bd..0000000000 --- a/crates/vfox/embedded-plugins/vfox-1password +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ac765040bda1f39ebf5be53a353eb949006b2c41 diff --git a/crates/vfox/embedded-plugins/vfox-1password/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-1password/hooks/available.lua new file mode 100644 index 0000000000..4659decfda --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-1password/hooks/available.lua @@ -0,0 +1,122 @@ +local http = require("http") + +--- Get the available version list. +--- @param ctx table Empty table, no data provided. Always {}. +--- @return table Version list +function PLUGIN:Available(ctx) + local result = {} + + -- Fetch CLI v2 versions (current) + local resp2 = http.get({ + url = "https://app-updates.agilebits.com/product_history/CLI2" + }) + if resp2.status_code == 200 then + -- Versions appear on lines after

tags + -- Pattern:

\n\t\t\t\tVERSION + for version in resp2.body:gmatch("

[^<]*

%s*([%d%.%-beta]+)") do + local clean_version = version:match("^%s*(.-)%s*$") + if clean_version and clean_version ~= "" then + table.insert(result, { + version = clean_version, + note = "CLI v2" + }) + end + end + -- Alternative pattern if the above doesn't work + if #result == 0 then + for version in resp2.body:gmatch("

%s*

%s*([%d%.%-beta]+)") do + local clean_version = version:match("^%s*(.-)%s*$") + if clean_version and clean_version ~= "" then + table.insert(result, { + version = clean_version, + note = "CLI v2" + }) + end + end + end + -- Try line-by-line parsing + if #result == 0 then + local in_h3 = false + for line in resp2.body:gmatch("[^\r\n]+") do + if line:match("

") then + in_h3 = true + elseif in_h3 then + local version = line:match("^%s*([%d%.%-beta]+)%s*$") + if version then + table.insert(result, { + version = version, + note = "CLI v2" + }) + end + in_h3 = false + end + end + end + end + + -- Fetch CLI v1 versions (legacy) + local resp1 = http.get({ + url = "https://app-updates.agilebits.com/product_history/CLI" + }) + if resp1.status_code == 200 then + local in_h3 = false + for line in resp1.body:gmatch("[^\r\n]+") do + if line:match("

") then + in_h3 = true + elseif in_h3 then + local version = line:match("^%s*([%d%.%-beta]+)%s*$") + if version then + table.insert(result, { + version = version, + note = "CLI v1" + }) + end + in_h3 = false + end + end + end + + -- Sort versions (newest first) + table.sort(result, function(a, b) + return compare_versions(a.version, b.version) + end) + + return result +end + +--- Compare two version strings +--- @param v1 string +--- @param v2 string +--- @return boolean true if v1 > v2 +function compare_versions(v1, v2) + local function parse(v) + local parts = {} + -- Handle beta versions: 2.31.0-beta.01 -> {2, 31, 0, -1, 1} + local main, beta = v:match("^([%d%.]+)%-beta%.?(%d*)$") + if main then + for num in main:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + table.insert(parts, -1) -- beta marker + if beta and beta ~= "" then + table.insert(parts, tonumber(beta)) + else + table.insert(parts, 0) + end + else + for num in v:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + end + return parts + end + + local p1, p2 = parse(v1), parse(v2) + for i = 1, math.max(#p1, #p2) do + local n1, n2 = p1[i] or 0, p2[i] or 0 + if n1 ~= n2 then + return n1 > n2 + end + end + return false +end diff --git a/crates/vfox/embedded-plugins/vfox-1password/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-1password/hooks/env_keys.lua new file mode 100644 index 0000000000..9b4d33dfa0 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-1password/hooks/env_keys.lua @@ -0,0 +1,12 @@ +--- Returns the environment variables that need to be set. +--- @param ctx table +--- @field ctx.path string Installation directory +--- @return table Environment variables +function PLUGIN:EnvKeys(ctx) + return { + { + key = "PATH", + value = ctx.path + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-1password/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-1password/hooks/pre_install.lua new file mode 100644 index 0000000000..4ef376df3f --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-1password/hooks/pre_install.lua @@ -0,0 +1,52 @@ +local http = require("http") + +--- Returns pre-installed information, such as version number, download address, etc. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + local version = ctx.version + local os_type = RUNTIME.osType + local arch_type = RUNTIME.archType + + -- Determine CLI version (v1 or v2) and base path + local cli_path + if version:match("^1%.") then + cli_path = "op" + else + cli_path = "op2" + end + + -- Map OS type + local os_name = os_type + if os_type == "darwin" then + os_name = "darwin" + elseif os_type == "windows" then + os_name = "windows" + end + + -- Map architecture + local arch = arch_type + if arch_type == "x86_64" then + arch = "amd64" + elseif arch_type == "i386" or arch_type == "i686" then + arch = "386" + elseif arch_type == "aarch64" then + arch = "arm64" + end + + local base_url = "https://cache.agilebits.com/dist/1P/" .. cli_path .. "/pkg/v" .. version .. "/" + local filename = "op_" .. os_name .. "_" .. arch .. "_v" .. version .. ".zip" + local download_url = base_url .. filename + + -- Verify URL exists + local resp = http.head({ url = download_url }) + if resp.status_code ~= 200 then + error("Download URL not found: " .. download_url .. " (status: " .. resp.status_code .. ")") + end + + return { + version = version, + url = download_url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-1password/metadata.lua b/crates/vfox/embedded-plugins/vfox-1password/metadata.lua new file mode 100644 index 0000000000..46b91c7350 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-1password/metadata.lua @@ -0,0 +1,20 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "1password" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-1password" +--- Plugin license +PLUGIN.license = "MIT" +--- Plugin description +PLUGIN.description = "1Password CLI (op) - Password manager developed by AgileBits Inc" + +--- !!! OPTIONAL !!! +PLUGIN.minRuntimeVersion = "0.3.0" +PLUGIN.notes = { + "Provides the 1Password CLI tool (op command)", +} diff --git a/crates/vfox/embedded-plugins/vfox-aapt2 b/crates/vfox/embedded-plugins/vfox-aapt2 deleted file mode 160000 index 144a5eafe7..0000000000 --- a/crates/vfox/embedded-plugins/vfox-aapt2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 144a5eafe7a76e954e91e8a9ca7aae99b895deda diff --git a/crates/vfox/embedded-plugins/vfox-aapt2/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/available.lua new file mode 100644 index 0000000000..8621fcd48b --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/available.lua @@ -0,0 +1,14 @@ +local util = require("util") + +--- Return all available versions provided by this plugin +--- @param ctx table Empty table used as context, for future extension +--- @return table Descriptions of available versions and accompanying tool descriptions +function PLUGIN:Available(ctx) + local versions = util.parseVersions() + + table.sort(versions, function(a, b) + return util.compareVersions(a.version, b.version) + end) + + return versions +end diff --git a/crates/vfox/embedded-plugins/vfox-aapt2/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/env_keys.lua new file mode 100644 index 0000000000..33b6c06c31 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/env_keys.lua @@ -0,0 +1,13 @@ +--- Each SDK may have different environment variable configurations. +--- This allows plugins to define custom environment variables (including PATH settings) +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +function PLUGIN:EnvKeys(ctx) + local mainPath = ctx.path + return { + { + key = "PATH", + value = mainPath + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-aapt2/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/post_install.lua new file mode 100644 index 0000000000..993242ce49 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/post_install.lua @@ -0,0 +1,57 @@ +local util = require("util") + +--- Extension point, called after PreInstall, can perform additional operations, +--- such as file operations for the SDK installation directory +--- @param ctx table +--- @field ctx.rootPath string SDK installation directory +function PLUGIN:PostInstall(ctx) + local rootPath = ctx.rootPath + local os_name = util.getOsName() + + -- Find the JAR file in the install directory + local find_cmd + local jar_path + if OS_TYPE == "windows" then + find_cmd = string.format('dir /b "%s\\aapt2-*.jar" 2>nul', rootPath) + else + find_cmd = string.format('ls "%s"/aapt2-*.jar 2>/dev/null | head -1', rootPath) + end + + local handle = io.popen(find_cmd) + if handle then + jar_path = handle:read("*l") + handle:close() + end + + if not jar_path or jar_path == "" then + -- JAR not found, maybe already extracted + return + end + + -- On Windows, need to prepend the rootPath + if OS_TYPE == "windows" and not string.match(jar_path, "^[A-Za-z]:") then + jar_path = rootPath .. "\\" .. jar_path + end + + -- Extract the JAR file (it's a ZIP) + local extract_cmd + if OS_TYPE == "windows" then + extract_cmd = string.format('powershell -Command "Expand-Archive -Path \'%s\' -DestinationPath \'%s\' -Force"', jar_path, rootPath) + else + extract_cmd = string.format('unzip -o "%s" -d "%s"', jar_path, rootPath) + end + + local result = os.execute(extract_cmd) + if not result then + error("Failed to extract JAR file: " .. jar_path) + end + + -- Remove the JAR file after extraction + os.remove(jar_path) + + -- Make the binary executable on Unix systems + if OS_TYPE ~= "windows" then + local aapt2_path = rootPath .. "/aapt2" + os.execute(string.format('chmod +x "%s"', aapt2_path)) + end +end diff --git a/crates/vfox/embedded-plugins/vfox-aapt2/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/pre_install.lua new file mode 100644 index 0000000000..bb5d4c2d88 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-aapt2/hooks/pre_install.lua @@ -0,0 +1,14 @@ +local util = require("util") + +--- Returns pre-installed information, such as version number, download address, etc. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + return { + version = version, + url = util.getDownloadUrl(version), + } +end diff --git a/crates/vfox/embedded-plugins/vfox-aapt2/lib/util.lua b/crates/vfox/embedded-plugins/vfox-aapt2/lib/util.lua new file mode 100644 index 0000000000..fcdaff13ea --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-aapt2/lib/util.lua @@ -0,0 +1,72 @@ +local http = require("http") + +local util = {} + +util.MAVEN_REPO = "https://dl.google.com/android/maven2/com/android/tools/build" +util.GROUP_INDEX_URL = util.MAVEN_REPO .. "/group-index.xml" + +function util.getOsName() + local os_type = OS_TYPE + if os_type == "darwin" then + return "osx" + elseif os_type == "linux" then + return "linux" + elseif os_type == "windows" then + return "windows" + else + error("Unsupported OS: " .. os_type) + end +end + +function util.getDownloadUrl(version) + local os_name = util.getOsName() + return string.format("%s/aapt2/%s/aapt2-%s-%s.jar", util.MAVEN_REPO, version, version, os_name) +end + +function util.parseVersions() + local resp, err = http.get({ + url = util.GROUP_INDEX_URL + }) + if err ~= nil or resp.status_code ~= 200 then + error("Failed to fetch version list: " .. (err or "HTTP " .. resp.status_code)) + end + + local result = {} + -- Parse versions from XML: + local versions_str = string.match(resp.body, ' b1 end + if a2 ~= b2 then return a2 > b2 end + if a3 ~= b3 then return a3 > b3 end + -- For suffix: stable (empty) > rc > beta > alpha + if a4 == "" and b4 ~= "" then return true end + if a4 ~= "" and b4 == "" then return false end + return a4 > b4 +end + +return util diff --git a/crates/vfox/embedded-plugins/vfox-aapt2/metadata.lua b/crates/vfox/embedded-plugins/vfox-aapt2/metadata.lua new file mode 100644 index 0000000000..69283344e4 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-aapt2/metadata.lua @@ -0,0 +1,20 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "aapt2" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-aapt2" +--- Plugin license +PLUGIN.license = "MIT" +--- Plugin description +PLUGIN.description = "Android Asset Packaging Tool 2 (aapt2)" + +--- !!! OPTIONAL !!! +PLUGIN.minRuntimeVersion = "0.3.0" +PLUGIN.notes = { + "aapt2 is used to compile and package Android app resources.", +} diff --git a/crates/vfox/embedded-plugins/vfox-ag b/crates/vfox/embedded-plugins/vfox-ag deleted file mode 160000 index 1ca4f81221..0000000000 --- a/crates/vfox/embedded-plugins/vfox-ag +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1ca4f81221b51a0d68de1bb958dede5762d6c08f diff --git a/crates/vfox/embedded-plugins/vfox-ag/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-ag/hooks/available.lua new file mode 100644 index 0000000000..2361c36808 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ag/hooks/available.lua @@ -0,0 +1,55 @@ +--- Returns all available versions of ag from GitHub tags +--- @param ctx table Context provided by vfox +--- @return table Available versions +function PLUGIN:Available(ctx) + local http = require("http") + local json = require("json") + + local result = {} + local page = 1 + + -- Get GitHub token from environment for rate limiting + local github_token = os.getenv("GITHUB_TOKEN") or os.getenv("GH_TOKEN") + local headers = { + ["Accept"] = "application/vnd.github.v3+json", + } + if github_token and github_token ~= "" then + headers["Authorization"] = "token " .. github_token + end + + while true do + local resp, err = http.get({ + url = "https://api.github.com/repos/ggreer/the_silver_searcher/tags?per_page=100&page=" .. page, + headers = headers, + }) + + if err ~= nil then + error("Failed to fetch tags: " .. err) + end + + if resp.status_code ~= 200 then + error("Failed to fetch tags, status: " .. resp.status_code) + end + + local tags = json.decode(resp.body) + if tags == nil or #tags == 0 then + break + end + + for _, tag in ipairs(tags) do + local version = tag.name + table.insert(result, { + version = version, + }) + end + + -- If we got less than 100 results, we've reached the end + if #tags < 100 then + break + end + + page = page + 1 + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-ag/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-ag/hooks/env_keys.lua new file mode 100644 index 0000000000..3b7a0480aa --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ag/hooks/env_keys.lua @@ -0,0 +1,14 @@ +--- Returns environment keys and paths for the installed tool +--- @param ctx table Context provided by vfox +--- @return table Environment keys +function PLUGIN:EnvKeys(ctx) + local mainSdk = ctx.sdkInfo["ag"] + local path = mainSdk.path + + return { + { + key = "PATH", + value = path .. "/bin", + }, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-ag/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-ag/hooks/post_install.lua new file mode 100644 index 0000000000..f46fb6b344 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ag/hooks/post_install.lua @@ -0,0 +1,31 @@ +--- Compiles ag from source after download +--- @param ctx table Context provided by vfox +function PLUGIN:PostInstall(ctx) + local cmd = require("cmd") + + local sdkInfo = ctx.sdkInfo["ag"] + local path = sdkInfo.path + + -- Source files are extracted directly to the install path + local srcDir = path + + --- Run autogen.sh to generate configure script + cmd.exec("cd '" .. srcDir .. "' && ./autogen.sh") + + --- Run configure with prefix set to installation path + --- Add -fcommon to CFLAGS for GCC 10+ compatibility (fixes multiple definition errors) + local configureArgs = os.getenv("AG_CONFIGURE_ARGS") or "" + local cflags = os.getenv("CFLAGS") or "" + if cflags == "" then + cflags = "-fcommon" + else + cflags = cflags .. " -fcommon" + end + cmd.exec("cd '" .. srcDir .. "' && CFLAGS='" .. cflags .. "' ./configure --prefix='" .. path .. "' " .. configureArgs) + + --- Run make + cmd.exec("cd '" .. srcDir .. "' && make") + + --- Run make install + cmd.exec("cd '" .. srcDir .. "' && make install") +end diff --git a/crates/vfox/embedded-plugins/vfox-ag/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-ag/hooks/pre_install.lua new file mode 100644 index 0000000000..302507f57e --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ag/hooks/pre_install.lua @@ -0,0 +1,18 @@ +--- Returns download information for a specific version +--- @param ctx table Context provided by vfox (contains version) +--- @return table Version info with download URL +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + if version == nil or version == "" then + error("You must provide a version number, eg: vfox install ag@2.2.0") + end + + -- Download source tarball from GitHub + local url = "https://github.com/ggreer/the_silver_searcher/archive/refs/tags/" .. version .. ".tar.gz" + + return { + version = version, + url = url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-ag/metadata.lua b/crates/vfox/embedded-plugins/vfox-ag/metadata.lua new file mode 100644 index 0000000000..d62fed86f7 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ag/metadata.lua @@ -0,0 +1,26 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "ag" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-ag" +--- Plugin license, please choose a correct license according to your needs. +PLUGIN.license = "Apache-2.0" +--- Plugin description +PLUGIN.description = "The Silver Searcher - A code searching tool similar to ack, with a focus on speed" + +--- !!! OPTIONAL !!! +--- Minimum compatible vfox version +PLUGIN.minRuntimeVersion = "0.3.0" +--- Manifest URL, if set, it will be used to check for updates +-- PLUGIN.manifestUrl = "https://github.com/mise-plugins/vfox-ag/releases/download/manifest/manifest.json" +--- User attention +PLUGIN.notes = { + "ag requires build dependencies: automake, pkg-config, pcre, xz, and a C compiler", + "On macOS: brew install automake pkg-config pcre xz", + "On Debian/Ubuntu: apt-get install automake pkg-config libpcre3-dev zlib1g-dev liblzma-dev", +} diff --git a/crates/vfox/embedded-plugins/vfox-android-sdk b/crates/vfox/embedded-plugins/vfox-android-sdk deleted file mode 160000 index 5f8b78d944..0000000000 --- a/crates/vfox/embedded-plugins/vfox-android-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f8b78d944f63f0c78775916aad0808a524148ae diff --git a/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/available.lua new file mode 100644 index 0000000000..7d921ad876 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/available.lua @@ -0,0 +1,39 @@ +--- Return all available versions provided by this plugin +--- @param ctx table Empty table used as context, for future extension +--- @return table Descriptions of available versions and accompanying tool descriptions +function PLUGIN:Available(ctx) + local http = require("http") + local env = require("env") + + local base_url = env.ANDROID_SDK_MIRROR_URL or "https://dl.google.com/android/repository" + local metadata_url = base_url .. "/repository2-3.xml" + + local resp = http.get({ url = metadata_url }) + if resp.status_code ~= 200 then + error("Failed to fetch Android SDK metadata: HTTP " .. resp.status_code) + end + + local versions = {} + local seen = {} + + -- Parse XML to find cmdline-tools packages + -- Look for remotePackage elements with path="cmdline-tools;VERSION" + for path_attr in resp.body:gmatch('remotePackage%s+path="([^"]+)"') do + -- Match cmdline-tools;VERSION pattern, excluding "latest" + local version = path_attr:match("^cmdline%-tools;(.+)$") + if version and version ~= "latest" and not seen[version] then + seen[version] = true + table.insert(versions, { + version = version, + note = "" + }) + end + end + + -- Sort versions (simple string sort, works for numeric versions) + table.sort(versions, function(a, b) + return a.version < b.version + end) + + return versions +end diff --git a/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/env_keys.lua new file mode 100644 index 0000000000..4702395a39 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/env_keys.lua @@ -0,0 +1,29 @@ +--- Return environment variables for the tool +--- @param ctx table +--- @field ctx.path string The installation path of the tool version +--- @field ctx.version string The version +--- @return table Environment variables +function PLUGIN:EnvKeys(ctx) + local file = require("file") + + local install_path = ctx.path + local version = ctx.version + + -- Structure is: install_path/cmdline-tools/VERSION/bin + local bin_path = file.join_path(install_path, "cmdline-tools", version, "bin") + + return { + { + key = "PATH", + value = bin_path + }, + { + key = "ANDROID_HOME", + value = install_path + }, + { + key = "ANDROID_SDK_ROOT", + value = install_path + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/post_install.lua new file mode 100644 index 0000000000..3c9ffd5964 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/post_install.lua @@ -0,0 +1,49 @@ +--- Called after the tool is installed. +--- Used to set up the correct directory structure for Android SDK. +--- @param ctx table +--- @field ctx.rootPath string The installation root path +--- @field ctx.sdkInfo table SDK information including version +function PLUGIN:PostInstall(ctx) + local file = require("file") + + local root_path = ctx.rootPath + + -- Get the version from sdkInfo + local version = nil + for _, info in pairs(ctx.sdkInfo) do + version = info.version + break + end + + if not version then + error("Could not determine version from sdkInfo") + end + + -- vfox extracts cmdline-tools contents directly to rootPath + -- But Android SDK expects: ANDROID_HOME/cmdline-tools/VERSION/bin/sdkmanager + -- So we need to reorganize: move rootPath/* to rootPath/cmdline-tools/VERSION/ + + local temp_path = root_path .. "-temp" + local target_path = file.join_path(root_path, "cmdline-tools", version) + + -- Move current rootPath to temp location + os.execute("mv " .. root_path .. " " .. temp_path) + + -- Recreate rootPath with proper structure + os.execute("mkdir -p " .. target_path) + + -- Move contents from temp to target + os.execute("mv " .. temp_path .. "/* " .. target_path .. "/") + + -- Clean up temp + os.execute("rm -rf " .. temp_path) + + -- Verify installation + local sdkmanager_path = file.join_path(target_path, "bin", "sdkmanager") + if not file.exists(sdkmanager_path) then + error("Installation verification failed: sdkmanager not found at " .. sdkmanager_path) + end + + -- Make sure binaries are executable (for Unix systems) + os.execute("chmod +x " .. file.join_path(target_path, "bin", "*") .. " 2>/dev/null || true") +end diff --git a/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/pre_install.lua new file mode 100644 index 0000000000..4c4806b354 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-android-sdk/hooks/pre_install.lua @@ -0,0 +1,106 @@ +--- Returns some pre-installed information, such as version number, download address, etc. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + local http = require("http") + local env = require("env") + + local version = ctx.version + + -- Determine OS (from global RUNTIME object) + local os_type = RUNTIME.osType + local android_sdk_os + if os_type == "darwin" then + android_sdk_os = "macosx" + elseif os_type == "linux" then + android_sdk_os = "linux" + elseif os_type == "windows" then + android_sdk_os = "windows" + else + error("Unsupported OS type: " .. os_type) + end + + -- Determine architecture (from global RUNTIME object) + local arch_type = RUNTIME.archType + local android_sdk_arch + if arch_type == "amd64" or arch_type == "x86_64" then + android_sdk_arch = "x64" + elseif arch_type == "arm64" or arch_type == "aarch64" then + android_sdk_arch = "aarch64" + else + error("Unsupported architecture: " .. arch_type) + end + + local base_url = env.ANDROID_SDK_MIRROR_URL or "https://dl.google.com/android/repository" + local metadata_url = base_url .. "/repository2-3.xml" + + local resp = http.get({ url = metadata_url }) + if resp.status_code ~= 200 then + error("Failed to fetch Android SDK metadata: HTTP " .. resp.status_code) + end + + -- Parse the XML to find the matching package + local package_pattern = 'remotePackage%s+path="cmdline%-tools;' .. version:gsub("%-", "%%-") .. '".-' + local package_block = resp.body:match(package_pattern) + + if not package_block then + error("Version " .. version .. " not found in Android SDK repository") + end + + -- Find archives block + local archives_block = package_block:match("(.-)") + if not archives_block then + error("No archives found for version " .. version) + end + + -- Find matching archive for our OS/arch + local best_archive = nil + + for archive in archives_block:gmatch("(.-)") do + local host_os = archive:match("([^<]+)") + local host_arch = archive:match("([^<]+)") + + -- Match if OS matches and either no arch specified or arch matches + if host_os == android_sdk_os then + if host_arch == nil or host_arch == android_sdk_arch then + best_archive = archive + -- Prefer exact arch match + if host_arch == android_sdk_arch then + break + end + end + end + end + + if not best_archive then + error("No archive found for " .. android_sdk_os .. ":" .. android_sdk_arch) + end + + -- Extract complete block (contains url, size, checksum) + local complete_block = best_archive:match("(.-)") + if not complete_block then + error("No complete block found in archive") + end + + -- Extract URL + local url = complete_block:match("([^<]+)") + if not url then + error("No URL found in archive") + end + + -- Make URL absolute if it's relative + if not url:match("^https?://") then + url = base_url .. "/" .. url + end + + local result = { + version = version, + url = url, + } + + -- Note: Android SDK only provides sha1 checksums, which vfox doesn't support yet + -- Checksum verification is skipped for now + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-android-sdk/metadata.lua b/crates/vfox/embedded-plugins/vfox-android-sdk/metadata.lua new file mode 100644 index 0000000000..609fbff67b --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-android-sdk/metadata.lua @@ -0,0 +1,23 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "android-sdk" +--- Plugin version +PLUGIN.version = "1.0.0" +--- Plugin homepage +PLUGIN.homepage = "https://developer.android.com/studio/command-line" +--- Plugin license +PLUGIN.license = "Apache 2.0" +--- Plugin description +PLUGIN.description = "Android SDK Command-line Tools" + +--- !!! OPTIONAL !!! +--- minimum compatible vfox version +PLUGIN.minRuntimeVersion = "0.3.0" +--- Some things that need user to be attention! +PLUGIN.notes = { + "Requires Java 11+ to be installed", + "Set ANDROID_SDK_MIRROR_URL to use a mirror" +} diff --git a/crates/vfox/embedded-plugins/vfox-ant b/crates/vfox/embedded-plugins/vfox-ant deleted file mode 160000 index 0254ebce47..0000000000 --- a/crates/vfox/embedded-plugins/vfox-ant +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0254ebce476d03b703604bd876d69f5026447c1a diff --git a/crates/vfox/embedded-plugins/vfox-ant/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-ant/hooks/available.lua new file mode 100644 index 0000000000..8621fcd48b --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ant/hooks/available.lua @@ -0,0 +1,14 @@ +local util = require("util") + +--- Return all available versions provided by this plugin +--- @param ctx table Empty table used as context, for future extension +--- @return table Descriptions of available versions and accompanying tool descriptions +function PLUGIN:Available(ctx) + local versions = util.parseVersions() + + table.sort(versions, function(a, b) + return util.compareVersions(a.version, b.version) + end) + + return versions +end diff --git a/crates/vfox/embedded-plugins/vfox-ant/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-ant/hooks/env_keys.lua new file mode 100644 index 0000000000..56e516d716 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ant/hooks/env_keys.lua @@ -0,0 +1,17 @@ +--- Each SDK may have different environment variable configurations. +--- This allows plugins to define custom environment variables (including PATH settings) +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +function PLUGIN:EnvKeys(ctx) + local mainPath = ctx.path + return { + { + key = "PATH", + value = mainPath .. "/bin" + }, + { + key = "ANT_HOME", + value = mainPath + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-ant/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-ant/hooks/post_install.lua new file mode 100644 index 0000000000..4c2ed55966 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ant/hooks/post_install.lua @@ -0,0 +1,8 @@ +--- Extension point, called after PreInstall, can perform additional operations, +--- such as file operations for the SDK installation directory +--- @param ctx table +--- @field ctx.rootPath string SDK installation directory +function PLUGIN:PostInstall(ctx) + -- The tarball extracts to apache-ant-{version}/ directory + -- mise should handle this automatically +end diff --git a/crates/vfox/embedded-plugins/vfox-ant/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-ant/hooks/pre_install.lua new file mode 100644 index 0000000000..0b41bc0403 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ant/hooks/pre_install.lua @@ -0,0 +1,40 @@ +local http = require("http") +local util = require("util") + +--- Returns pre-installed information, such as version number, download address, etc. +--- If checksum is provided, vfox will automatically check it for you. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + -- Try to get checksum (sha512 first, then sha1) + local checksums = { + { type = "sha512", url = util.CHECKSUM_URL:format(version, "sha512") }, + { type = "sha1", url = util.CHECKSUM_URL:format(version, "sha1") }, + } + + for _, checksum in ipairs(checksums) do + local resp, err = http.get({ + url = checksum.url + }) + if err == nil and resp.status_code == 200 then + local hash = string.match(resp.body, "^(%S+)") + if hash then + local result = { + version = version, + url = util.FILE_URL:format(version), + } + result[checksum.type] = hash + return result + end + end + end + + -- No checksum found, return without checksum + return { + version = version, + url = util.FILE_URL:format(version), + } +end diff --git a/crates/vfox/embedded-plugins/vfox-ant/lib/util.lua b/crates/vfox/embedded-plugins/vfox-ant/lib/util.lua new file mode 100644 index 0000000000..420e3e2095 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ant/lib/util.lua @@ -0,0 +1,56 @@ +local http = require("http") +local html = require("html") + +local util = {} + +util.ARCHIVE_URL = "https://archive.apache.org/dist/ant/binaries/" +util.FILE_URL = "https://archive.apache.org/dist/ant/binaries/apache-ant-%s-bin.tar.gz" +util.CHECKSUM_URL = "https://archive.apache.org/dist/ant/binaries/apache-ant-%s-bin.tar.gz.%s" + +function util.parseVersions() + local resp, err = http.get({ + url = util.ARCHIVE_URL + }) + if err ~= nil or resp.status_code ~= 200 then + error("Failed to fetch version list: " .. (err or "HTTP " .. resp.status_code)) + end + + local result = {} + html.parse(resp.body):find("a"):each(function(i, selection) + local href = selection:attr("href") + -- Match apache-ant-X.Y.Z-bin.tar.gz + local version = string.match(href, "^apache%-ant%-([%d%.]+)%-bin%.tar%.gz$") + if version then + table.insert(result, { + version = version, + note = "", + }) + end + end) + + return result +end + +function util.compareVersions(a, b) + local function parseVersion(v) + local parts = {} + for part in string.gmatch(v, "([^.]+)") do + table.insert(parts, tonumber(part) or 0) + end + return parts + end + + local pa = parseVersion(a) + local pb = parseVersion(b) + + for i = 1, math.max(#pa, #pb) do + local va = pa[i] or 0 + local vb = pb[i] or 0 + if va ~= vb then + return va > vb + end + end + return false +end + +return util diff --git a/crates/vfox/embedded-plugins/vfox-ant/metadata.lua b/crates/vfox/embedded-plugins/vfox-ant/metadata.lua new file mode 100644 index 0000000000..587fa88a7a --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-ant/metadata.lua @@ -0,0 +1,20 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "ant" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-ant" +--- Plugin license +PLUGIN.license = "MIT" +--- Plugin description +PLUGIN.description = "Apache Ant build tool" + +--- !!! OPTIONAL !!! +PLUGIN.minRuntimeVersion = "0.3.0" +PLUGIN.notes = { + "Apache Ant is a Java library and command-line tool for building Java applications.", +} diff --git a/crates/vfox/embedded-plugins/vfox-asciidoctorj b/crates/vfox/embedded-plugins/vfox-asciidoctorj deleted file mode 160000 index 49b6a49fe4..0000000000 --- a/crates/vfox/embedded-plugins/vfox-asciidoctorj +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 49b6a49fe49cf290f2977a4a84cac6cda7faba19 diff --git a/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/available.lua new file mode 100644 index 0000000000..a78b91d2b4 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/available.lua @@ -0,0 +1,61 @@ +local http = require("http") + +--- Get the available version list from Maven Central. +--- @param ctx table Empty table, no data provided. Always {}. +--- @return table Version list +function PLUGIN:Available(ctx) + local result = {} + + local resp = http.get({ + url = "https://repo1.maven.org/maven2/org/asciidoctor/asciidoctorj/" + }) + + if resp.status_code ~= 200 then + error("Failed to fetch versions from Maven Central: " .. resp.status_code) + end + + -- Parse version directories from Maven Central HTML + -- Pattern matches: + for version in resp.body:gmatch(' 1 or (major == 1 and minor >= 5) then + table.insert(result, { + version = version + }) + end + end + end + + -- Sort versions (newest first) + table.sort(result, function(a, b) + return compare_versions(a.version, b.version) + end) + + return result +end + +--- Compare two version strings +--- @param v1 string +--- @param v2 string +--- @return boolean true if v1 > v2 +function compare_versions(v1, v2) + local function parse(v) + local parts = {} + for num in v:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + return parts + end + + local p1, p2 = parse(v1), parse(v2) + for i = 1, math.max(#p1, #p2) do + local n1, n2 = p1[i] or 0, p2[i] or 0 + if n1 ~= n2 then + return n1 > n2 + end + end + return false +end diff --git a/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/env_keys.lua new file mode 100644 index 0000000000..779ff9ca72 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/env_keys.lua @@ -0,0 +1,13 @@ +--- Sets environment variables for the installed version. +--- @param ctx table +--- @field ctx.path string Installation path +--- @return table Environment variables +function PLUGIN:EnvKeys(ctx) + -- mise flattens the zip structure, so bin is directly in ctx.path + return { + { + key = "PATH", + value = ctx.path .. "/bin" + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/pre_install.lua new file mode 100644 index 0000000000..11ee797202 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-asciidoctorj/hooks/pre_install.lua @@ -0,0 +1,23 @@ +local http = require("http") + +--- Returns pre-installed information, such as version number, download address, etc. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + local base_url = "https://repo1.maven.org/maven2/org/asciidoctor/asciidoctorj/" + local download_url = base_url .. version .. "/asciidoctorj-" .. version .. "-bin.zip" + + -- Verify URL exists + local resp = http.head({ url = download_url }) + if resp.status_code ~= 200 then + error("Download URL not found: " .. download_url .. " (status: " .. resp.status_code .. ")") + end + + return { + version = version, + url = download_url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-asciidoctorj/metadata.lua b/crates/vfox/embedded-plugins/vfox-asciidoctorj/metadata.lua new file mode 100644 index 0000000000..0cad0eed42 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-asciidoctorj/metadata.lua @@ -0,0 +1,21 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "asciidoctorj" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-asciidoctorj" +--- Plugin license +PLUGIN.license = "MIT" +--- Plugin description +PLUGIN.description = "AsciidoctorJ - the official library for running Asciidoctor on the JVM" + +--- !!! OPTIONAL !!! +PLUGIN.minRuntimeVersion = "0.3.0" +PLUGIN.notes = { + "Provides the asciidoctorj command for converting AsciiDoc documents", + "Requires Java to be installed", +} diff --git a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools deleted file mode 160000 index 030fc1ca68..0000000000 --- a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 030fc1ca682ed548af30e2a3562d01904ad8d586 diff --git a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/available.lua new file mode 100644 index 0000000000..00e29d6ab2 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/available.lua @@ -0,0 +1,51 @@ +local http = require("http") +local json = require("json") + +--- Get the available version list from GitHub releases. +--- @param ctx table Empty table, no data provided. Always {}. +--- @return table Version list +function PLUGIN:Available(ctx) + local result = {} + local page = 1 + local per_page = 100 + + while true do + local url = "https://api.github.com/repos/Azure/azure-functions-core-tools/releases?per_page=" .. per_page .. "&page=" .. page + local resp = http.get({ + url = url, + headers = { + ["Accept"] = "application/vnd.github.v3+json" + } + }) + + if resp.status_code ~= 200 then + if page == 1 then + error("Failed to fetch releases from GitHub: " .. resp.status_code) + end + break + end + + local releases = json.decode(resp.body) + if #releases == 0 then + break + end + + for _, release in ipairs(releases) do + if not release.prerelease and not release.draft then + local version = release.tag_name + table.insert(result, { + version = version, + note = release.name or "" + }) + end + end + + page = page + 1 + -- Limit to avoid too many API calls + if page > 5 then + break + end + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/env_keys.lua new file mode 100644 index 0000000000..9f24c21a68 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/env_keys.lua @@ -0,0 +1,13 @@ +--- Sets environment variables for the installed version. +--- @param ctx table +--- @field ctx.path string Installation path +--- @return table Environment variables +function PLUGIN:EnvKeys(ctx) + -- The func binary is at the root of the extracted zip + return { + { + key = "PATH", + value = ctx.path + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/post_install.lua new file mode 100644 index 0000000000..696bac8f9e --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/post_install.lua @@ -0,0 +1,24 @@ +--- Called after installation is complete to fix binary permissions. +--- @param ctx table +--- @field ctx.rootPath string Installation root path +function PLUGIN:PostInstall(ctx) + local os_type = RUNTIME.osType + + -- On Unix systems, we need to make the binary executable + if os_type ~= "windows" then + local func_path = ctx.rootPath .. "/func" + -- Use os.execute to chmod +x the binary + local result = os.execute("chmod +x " .. func_path) + if result ~= 0 and result ~= true then + -- Some Lua versions return true on success, others return 0 + print("Warning: could not chmod +x " .. func_path) + end + + -- Also chmod other potential executables + local gozip_path = ctx.rootPath .. "/gozip" + os.execute("chmod +x " .. gozip_path .. " 2>/dev/null") + + local createdump_path = ctx.rootPath .. "/createdump" + os.execute("chmod +x " .. createdump_path .. " 2>/dev/null") + end +end diff --git a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/pre_install.lua new file mode 100644 index 0000000000..330c8b9952 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/hooks/pre_install.lua @@ -0,0 +1,48 @@ +local http = require("http") + +--- Returns pre-installed information, such as version number, download address, etc. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + local version = ctx.version + local os_type = RUNTIME.osType + local arch_type = RUNTIME.archType + + -- Map OS type to Azure naming convention + local os_name + if os_type == "darwin" then + os_name = "osx" + elseif os_type == "windows" then + os_name = "win" + else + os_name = "linux" + end + + -- Map architecture + local arch + if arch_type == "amd64" or arch_type == "x86_64" then + arch = "x64" + elseif arch_type == "arm64" or arch_type == "aarch64" then + arch = "arm64" + elseif arch_type == "386" or arch_type == "i386" or arch_type == "i686" then + arch = "x86" + else + arch = arch_type + end + + local base_url = "https://github.com/Azure/azure-functions-core-tools/releases/download/" + local filename = "Azure.Functions.Cli." .. os_name .. "-" .. arch .. "." .. version .. ".zip" + local download_url = base_url .. version .. "/" .. filename + + -- Verify URL exists + local resp = http.head({ url = download_url }) + if resp.status_code ~= 200 and resp.status_code ~= 302 then + error("Download URL not found: " .. download_url .. " (status: " .. resp.status_code .. ")") + end + + return { + version = version, + url = download_url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/metadata.lua b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/metadata.lua new file mode 100644 index 0000000000..545a0767a1 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-azure-functions-core-tools/metadata.lua @@ -0,0 +1,20 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "azure-functions-core-tools" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-azure-functions-core-tools" +--- Plugin license +PLUGIN.license = "MIT" +--- Plugin description +PLUGIN.description = "Azure Functions Core Tools - Command line tools for Azure Functions" + +--- !!! OPTIONAL !!! +PLUGIN.minRuntimeVersion = "0.3.0" +PLUGIN.notes = { + "Provides the 'func' command for local Azure Functions development", +} diff --git a/crates/vfox/embedded-plugins/vfox-bfs b/crates/vfox/embedded-plugins/vfox-bfs deleted file mode 160000 index 165106df1d..0000000000 --- a/crates/vfox/embedded-plugins/vfox-bfs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 165106df1da197070e2d56edf0661f1cb2e2699d diff --git a/crates/vfox/embedded-plugins/vfox-bfs/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-bfs/hooks/available.lua new file mode 100644 index 0000000000..649ef2dbd5 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bfs/hooks/available.lua @@ -0,0 +1,18 @@ +--- Returns all available versions of bfs from GitHub tags +--- @param ctx table Context object (unused for this plugin) +--- @return table Array of version objects with 'version' field +function PLUGIN:Available(ctx) + local util = require("util") + local versions = util.get_versions() + + -- Sort versions (newest first) + table.sort(versions, util.version_compare) + + -- Convert to vfox format + local result = {} + for _, v in ipairs(versions) do + table.insert(result, { version = v }) + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-bfs/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-bfs/hooks/env_keys.lua new file mode 100644 index 0000000000..dde6c264a8 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bfs/hooks/env_keys.lua @@ -0,0 +1,12 @@ +--- Each SDK may have different environment variable configurations. +--- This allows plugins to define custom environment variables (including PATH settings) +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +function PLUGIN:EnvKeys(ctx) + return { + { + key = "PATH", + value = ctx.path .. "/bin" + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-bfs/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-bfs/hooks/post_install.lua new file mode 100644 index 0000000000..6c754b8966 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bfs/hooks/post_install.lua @@ -0,0 +1,36 @@ +--- Extension point, called after PreInstall, compiles bfs from source +--- @param ctx table +--- @field ctx.rootPath string SDK installation directory +function PLUGIN:PostInstall(ctx) + local rootPath = ctx.rootPath + + -- mise extracts the tarball and moves content directly to rootPath + -- So rootPath IS the source directory + + -- Check if configure script exists (to verify we're in the right place) + local check_cmd = string.format('test -f "%s/configure"', rootPath) + local exists = os.execute(check_cmd) + if not exists then + error("Could not find configure script in " .. rootPath .. ". The source may not have been extracted correctly.") + end + + -- Build bfs using configure && make + -- RELEASE=y enables optimizations + local build_cmd = string.format( + 'cd "%s" && ./configure RELEASE=y && make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)', + rootPath + ) + + print("Compiling bfs from source...") + local result = os.execute(build_cmd) + if not result then + error("Failed to compile bfs. Make sure you have a C compiler (gcc/clang) and make installed.") + end + + -- bfs binary is built in bin/ subdirectory + -- Make sure it's executable + local binPath = rootPath .. "/bin" + os.execute(string.format('chmod +x "%s/bfs"', binPath)) + + print("bfs compiled successfully!") +end diff --git a/crates/vfox/embedded-plugins/vfox-bfs/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-bfs/hooks/pre_install.lua new file mode 100644 index 0000000000..b1ce4e0521 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bfs/hooks/pre_install.lua @@ -0,0 +1,19 @@ +--- Returns information about where to download the bfs source tarball +--- @param ctx table Context containing version info +--- @field ctx.version string The version to install +--- @return table Installation info including download URL +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + -- bfs releases source tarballs on GitHub + -- URL format: https://github.com/tavianator/bfs/archive/refs/tags/{version}.tar.gz + local url = string.format( + "https://github.com/tavianator/bfs/archive/refs/tags/%s.tar.gz", + version + ) + + return { + version = version, + url = url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-bfs/lib/util.lua b/crates/vfox/embedded-plugins/vfox-bfs/lib/util.lua new file mode 100644 index 0000000000..90169c9461 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bfs/lib/util.lua @@ -0,0 +1,68 @@ +--- Utility functions for the bfs vfox plugin + +local util = {} + +--- Fetch content from a URL using curl +--- @param url string The URL to fetch +--- @return string|nil content The response body or nil on error +function util.fetch(url) + local handle = io.popen(string.format('curl -sfL "%s"', url)) + if not handle then + return nil + end + local content = handle:read("*a") + handle:close() + if content == "" then + return nil + end + return content +end + +--- Get all version tags from GitHub releases +--- @return table versions List of version strings +function util.get_versions() + local versions = {} + local url = "https://api.github.com/repos/tavianator/bfs/tags?per_page=100" + local content = util.fetch(url) + if not content then + return versions + end + + -- Parse JSON to extract tag names (versions) + for tag in content:gmatch('"name"%s*:%s*"([^"]+)"') do + -- bfs uses tags like "4.0.4", "4.1", etc. (no 'v' prefix) + if tag:match("^%d+%.%d+") then + table.insert(versions, tag) + end + end + + return versions +end + +--- Compare version strings for sorting (descending - newest first) +--- @param a string First version +--- @param b string Second version +--- @return boolean true if a > b +function util.version_compare(a, b) + local function parse_version(v) + local parts = {} + for num in v:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + return parts + end + + local pa = parse_version(a) + local pb = parse_version(b) + + for i = 1, math.max(#pa, #pb) do + local na = pa[i] or 0 + local nb = pb[i] or 0 + if na ~= nb then + return na > nb + end + end + return false +end + +return util diff --git a/crates/vfox/embedded-plugins/vfox-bfs/metadata.lua b/crates/vfox/embedded-plugins/vfox-bfs/metadata.lua new file mode 100644 index 0000000000..faa2feba11 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bfs/metadata.lua @@ -0,0 +1,26 @@ +--- Plugin metadata for mise/vfox integration +PLUGIN = {} + +--- Plugin name +PLUGIN.name = "bfs" + +--- Plugin version (SemVer) +PLUGIN.version = "0.1.0" + +--- Plugin description +PLUGIN.description = "A breadth-first version of the UNIX find command" + +--- Minimum vfox version required +PLUGIN.minRuntimeVersion = "0.3.0" + +--- Repository URL +PLUGIN.repository = "https://github.com/mise-plugins/vfox-bfs" + +--- Tool homepage +PLUGIN.homepage = "https://tavianator.com/projects/bfs.html" + +--- License +PLUGIN.license = "0BSD" + +--- Notes about this plugin +PLUGIN.notes = "Compiles from source. Requires a C compiler (gcc/clang) and make." diff --git a/crates/vfox/embedded-plugins/vfox-bpkg b/crates/vfox/embedded-plugins/vfox-bpkg deleted file mode 160000 index 365ac71fbd..0000000000 --- a/crates/vfox/embedded-plugins/vfox-bpkg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 365ac71fbdfdd9372dcd42796a9bdb1b67171370 diff --git a/crates/vfox/embedded-plugins/vfox-bpkg/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/available.lua new file mode 100644 index 0000000000..27c095f10b --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/available.lua @@ -0,0 +1,49 @@ +--- Returns all available versions of bpkg from GitHub releases +--- @param ctx table Context provided by vfox +--- @return table Available versions +function PLUGIN:Available(ctx) + local http = require("http") + local json = require("json") + + local result = {} + + -- Get GitHub token from environment if available + local github_token = os.getenv("GITHUB_TOKEN") or os.getenv("GH_TOKEN") + local headers = { + ["Accept"] = "application/vnd.github.v3+json", + } + if github_token and github_token ~= "" then + headers["Authorization"] = "token " .. github_token + end + + local resp, err = http.get({ + url = "https://api.github.com/repos/bpkg/bpkg/tags", + headers = headers + }) + + if err ~= nil then + error("Failed to fetch versions: " .. err) + end + + if resp.status_code ~= 200 then + error("Failed to fetch versions, status: " .. resp.status_code) + end + + local tags = json.decode(resp.body) + if tags == nil then + return result + end + + for _, tag in ipairs(tags) do + local version = tag.name + -- Remove 'v' prefix if present + if version:sub(1, 1) == "v" then + version = version:sub(2) + end + table.insert(result, { + version = version, + }) + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-bpkg/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/env_keys.lua new file mode 100644 index 0000000000..5e73da38e3 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/env_keys.lua @@ -0,0 +1,14 @@ +--- Returns environment keys and paths for the installed tool +--- @param ctx table Context provided by vfox +--- @return table Environment keys +function PLUGIN:EnvKeys(ctx) + local mainSdk = ctx.sdkInfo["bpkg"] + local path = mainSdk.path + + return { + { + key = "PATH", + value = path .. "/bin", + }, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-bpkg/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/post_install.lua new file mode 100644 index 0000000000..987108b880 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/post_install.lua @@ -0,0 +1,73 @@ +--- Installs bpkg by copying bash scripts to bin directory +--- @param ctx table Context provided by vfox +function PLUGIN:PostInstall(ctx) + local cmd = require("cmd") + + local sdkInfo = ctx.sdkInfo["bpkg"] + local path = sdkInfo.path + local version = sdkInfo.version + + -- The tarball may extract to bpkg-{version}/ or directly to path + -- Check which case we have + local srcDir = path .. "/bpkg-" .. version + local file = io.open(srcDir .. "/bpkg.sh", "r") + if file then + file:close() + else + -- Files are directly in path + srcDir = path + end + + -- Create bin directory + cmd.exec("mkdir -p '" .. path .. "/bin'") + + -- bpkg uses symlinks to lib/ directory, so we need to: + -- 1. Copy the lib directory + -- 2. Copy the main bpkg.sh script + -- 3. Copy the symlinks (they point to lib/) + + -- Copy lib directory + cmd.exec("cp -r '" .. srcDir .. "/lib' '" .. path .. "/bin/'") + + -- Copy main script + cmd.exec("cp -f '" .. srcDir .. "/bpkg.sh' '" .. path .. "/bin/'") + + -- Copy all symlinks (they'll still point to lib/ which we copied) + local scripts = { + "bpkg", + "bpkg-env", + "bpkg-getdeps", + "bpkg-init", + "bpkg-install", + "bpkg-json", + "bpkg-list", + "bpkg-package", + "bpkg-run", + "bpkg-show", + "bpkg-source", + "bpkg-suggest", + "bpkg-term", + "bpkg-update", + "bpkg-utils", + "bpkg-realpath", + } + + for _, script in ipairs(scripts) do + local src = srcDir .. "/" .. script + local dst = path .. "/bin/" .. script + -- Copy symlink as symlink (-P preserves symlinks) + cmd.exec("cp -P '" .. src .. "' '" .. dst .. "' 2>/dev/null || true") + end + + -- Make all scripts executable + cmd.exec("chmod +x '" .. path .. "/bin/bpkg.sh'") + cmd.exec("find '" .. path .. "/bin/lib' -name '*.sh' -exec chmod +x {} \\;") + + -- Verify main bpkg script was installed + local file = io.open(path .. "/bin/bpkg.sh", "r") + if file then + file:close() + else + error("Failed to install bpkg - main script not found at " .. path .. "/bin/bpkg.sh") + end +end diff --git a/crates/vfox/embedded-plugins/vfox-bpkg/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/pre_install.lua new file mode 100644 index 0000000000..d960313e64 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bpkg/hooks/pre_install.lua @@ -0,0 +1,18 @@ +--- Returns version information for installation +--- @param ctx table Context provided by vfox (contains version) +--- @return table Version info with download URL +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + if version == nil or version == "" then + error("You must provide a version number, eg: vfox install bpkg@1.1.3") + end + + -- bpkg releases don't have a 'v' prefix in the tarball URL + local url = "https://github.com/bpkg/bpkg/archive/refs/tags/" .. version .. ".tar.gz" + + return { + version = version, + url = url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-bpkg/metadata.lua b/crates/vfox/embedded-plugins/vfox-bpkg/metadata.lua new file mode 100644 index 0000000000..ae343bf046 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-bpkg/metadata.lua @@ -0,0 +1,12 @@ +--- Plugin metadata +PLUGIN = {} + +PLUGIN.name = "bpkg" +PLUGIN.version = "0.1.0" +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-bpkg" +PLUGIN.license = "Apache-2.0" +PLUGIN.description = "Lightweight bash package manager" +PLUGIN.notes = "Requires bash" + +--- Minimum vfox version required +PLUGIN.minRuntimeVersion = "0.3.0" diff --git a/crates/vfox/embedded-plugins/vfox-carthage b/crates/vfox/embedded-plugins/vfox-carthage deleted file mode 160000 index dd0ff56c03..0000000000 --- a/crates/vfox/embedded-plugins/vfox-carthage +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dd0ff56c03384624e1983d6948f2b54f14ea61ba diff --git a/crates/vfox/embedded-plugins/vfox-carthage/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-carthage/hooks/available.lua new file mode 100644 index 0000000000..dd2d0e7d0d --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-carthage/hooks/available.lua @@ -0,0 +1,18 @@ +--- Returns all available versions of carthage from GitHub releases +--- @param ctx table Context object (unused for this plugin) +--- @return table Array of version objects with 'version' field +function PLUGIN:Available(ctx) + local util = require("util") + local versions = util.get_versions() + + -- Sort versions (newest first) + table.sort(versions, util.version_compare) + + -- Convert to vfox format + local result = {} + for _, v in ipairs(versions) do + table.insert(result, { version = v }) + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-carthage/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-carthage/hooks/env_keys.lua new file mode 100644 index 0000000000..dde6c264a8 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-carthage/hooks/env_keys.lua @@ -0,0 +1,12 @@ +--- Each SDK may have different environment variable configurations. +--- This allows plugins to define custom environment variables (including PATH settings) +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +function PLUGIN:EnvKeys(ctx) + return { + { + key = "PATH", + value = ctx.path .. "/bin" + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-carthage/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-carthage/hooks/post_install.lua new file mode 100644 index 0000000000..3a8a759282 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-carthage/hooks/post_install.lua @@ -0,0 +1,70 @@ +--- Extension point, called after PreInstall, extracts carthage from .pkg +--- @param ctx table +--- @field ctx.rootPath string SDK installation directory +function PLUGIN:PostInstall(ctx) + local rootPath = ctx.rootPath + + -- Check if we're on macOS (carthage is macOS only) + if OS_TYPE ~= "darwin" then + error("Carthage is only available for macOS") + end + + -- Find the downloaded .pkg file + local find_cmd = string.format('ls "%s"/*.pkg 2>/dev/null | head -1', rootPath) + local handle = io.popen(find_cmd) + if not handle then + error("Failed to find .pkg file") + end + local pkg_path = handle:read("*l") + handle:close() + + if not pkg_path or pkg_path == "" then + error("Could not find Carthage.pkg in " .. rootPath) + end + + -- Create extraction directory + local expand_dir = rootPath .. "/expanded" + os.execute(string.format('mkdir -p "%s"', expand_dir)) + + -- Expand the .pkg file using pkgutil + local expand_cmd = string.format('pkgutil --expand "%s" "%s"', pkg_path, expand_dir) + local result = os.execute(expand_cmd) + if not result then + error("Failed to expand .pkg file") + end + + -- Find the payload and extract it + -- The payload is typically in CarthageApp.pkg/Payload + local payload_dir = expand_dir .. "/CarthageApp.pkg" + local extract_cmd = string.format( + 'cd "%s" && cat Payload | gunzip | cpio -id 2>/dev/null', + payload_dir + ) + result = os.execute(extract_cmd) + if not result then + error("Failed to extract payload from .pkg") + end + + -- Create bin directory and move carthage binary + local binDir = rootPath .. "/bin" + os.execute(string.format('mkdir -p "%s"', binDir)) + + local move_cmd = string.format( + 'mv "%s/usr/local/bin/carthage" "%s/carthage"', + payload_dir, binDir + ) + result = os.execute(move_cmd) + if not result then + error("Failed to move carthage binary to bin directory") + end + + -- Make executable and remove quarantine + os.execute(string.format('chmod +x "%s/carthage"', binDir)) + os.execute(string.format('xattr -d com.apple.quarantine "%s/carthage" 2>/dev/null || true', binDir)) + + -- Clean up + os.execute(string.format('rm -rf "%s"', expand_dir)) + os.execute(string.format('rm -f "%s"', pkg_path)) + + print("Carthage installed successfully!") +end diff --git a/crates/vfox/embedded-plugins/vfox-carthage/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-carthage/hooks/pre_install.lua new file mode 100644 index 0000000000..9aa1b16380 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-carthage/hooks/pre_install.lua @@ -0,0 +1,18 @@ +--- Returns information about where to download the carthage .pkg +--- @param ctx table Context containing version info +--- @field ctx.version string The version to install +--- @return table Installation info including download URL +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + -- Carthage releases .pkg files on GitHub + local url = string.format( + "https://github.com/Carthage/Carthage/releases/download/%s/Carthage.pkg", + version + ) + + return { + version = version, + url = url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-carthage/lib/util.lua b/crates/vfox/embedded-plugins/vfox-carthage/lib/util.lua new file mode 100644 index 0000000000..23543c3353 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-carthage/lib/util.lua @@ -0,0 +1,68 @@ +--- Utility functions for the carthage vfox plugin + +local util = {} + +--- Fetch content from a URL using curl +--- @param url string The URL to fetch +--- @return string|nil content The response body or nil on error +function util.fetch(url) + local handle = io.popen(string.format('curl -sfL "%s"', url)) + if not handle then + return nil + end + local content = handle:read("*a") + handle:close() + if content == "" then + return nil + end + return content +end + +--- Get all version tags from GitHub releases +--- @return table versions List of version strings +function util.get_versions() + local versions = {} + local url = "https://api.github.com/repos/Carthage/Carthage/releases?per_page=100" + local content = util.fetch(url) + if not content then + return versions + end + + -- Parse JSON to extract tag names (versions) + for tag in content:gmatch('"tag_name"%s*:%s*"([^"]+)"') do + -- Carthage uses tags like "0.40.0", "0.39.1", etc. + if tag:match("^%d+%.%d+") then + table.insert(versions, tag) + end + end + + return versions +end + +--- Compare version strings for sorting (descending - newest first) +--- @param a string First version +--- @param b string Second version +--- @return boolean true if a > b +function util.version_compare(a, b) + local function parse_version(v) + local parts = {} + for num in v:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + return parts + end + + local pa = parse_version(a) + local pb = parse_version(b) + + for i = 1, math.max(#pa, #pb) do + local na = pa[i] or 0 + local nb = pb[i] or 0 + if na ~= nb then + return na > nb + end + end + return false +end + +return util diff --git a/crates/vfox/embedded-plugins/vfox-carthage/metadata.lua b/crates/vfox/embedded-plugins/vfox-carthage/metadata.lua new file mode 100644 index 0000000000..efa0583c54 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-carthage/metadata.lua @@ -0,0 +1,26 @@ +--- Plugin metadata for mise/vfox integration +PLUGIN = {} + +--- Plugin name +PLUGIN.name = "carthage" + +--- Plugin version (SemVer) +PLUGIN.version = "0.1.0" + +--- Plugin description +PLUGIN.description = "A simple, decentralized dependency manager for Cocoa" + +--- Minimum vfox version required +PLUGIN.minRuntimeVersion = "0.3.0" + +--- Repository URL +PLUGIN.repository = "https://github.com/mise-plugins/vfox-carthage" + +--- Tool homepage +PLUGIN.homepage = "https://github.com/Carthage/Carthage" + +--- License +PLUGIN.license = "MIT" + +--- Notes about this plugin +PLUGIN.notes = "macOS only. Extracts binary from .pkg installer." diff --git a/crates/vfox/embedded-plugins/vfox-chezscheme b/crates/vfox/embedded-plugins/vfox-chezscheme deleted file mode 160000 index 486347df3b..0000000000 --- a/crates/vfox/embedded-plugins/vfox-chezscheme +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 486347df3b45edd310e5455aa0eb54198facb620 diff --git a/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/available.lua new file mode 100644 index 0000000000..5d33ff54b1 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/available.lua @@ -0,0 +1,41 @@ +local http = require("http") +local json = require("json") + +--- Returns all available versions of Chez Scheme from GitHub tags. +--- @param ctx table Context +--- @return table Available versions +function PLUGIN:Available(ctx) + local results = {} + + -- Fetch releases from GitHub API (tags show up as releases) + local resp, err = http.get({ + url = "https://api.github.com/repos/cisco/ChezScheme/tags?per_page=100" + }) + + if err ~= nil then + error("Failed to fetch versions: " .. err) + end + + if resp.status_code ~= 200 then + error("Failed to fetch versions: HTTP " .. resp.status_code) + end + + local tags = json.decode(resp.body) + + for _, tag in ipairs(tags) do + local version = tag.name + -- Remove 'v' prefix if present + if version:sub(1, 1) == "v" then + version = version:sub(2) + end + -- Only include version-like tags (e.g., 10.3.0, 9.5.8) + if version:match("^%d+%.%d+") then + table.insert(results, { + version = version, + note = "" + }) + end + end + + return results +end diff --git a/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/env_keys.lua new file mode 100644 index 0000000000..6cb87320bd --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/env_keys.lua @@ -0,0 +1,12 @@ +--- Returns environment variables to set for this tool. +--- @param ctx table +--- @field ctx.path string Installation path +--- @return table Environment variables +function PLUGIN:EnvKeys(ctx) + return { + { + key = "PATH", + value = ctx.path .. "/bin" + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/post_install.lua new file mode 100644 index 0000000000..c2ba9ef0e3 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/post_install.lua @@ -0,0 +1,49 @@ +--- Called after extraction to compile Chez Scheme from source. +--- @param ctx table +--- @field ctx.rootPath string Installation root path +function PLUGIN:PostInstall(ctx) + local os_type = RUNTIME.osType + + -- Windows uses the .exe installer, not source compilation + if os_type == "windows" then + print("Windows installation requires the ChezScheme.exe installer from GitHub releases") + print("Please download and run it manually from:") + print("https://github.com/cisco/ChezScheme/releases") + return + end + + local root_path = ctx.rootPath + + -- The tarball extracts with contents at root level (no top-level directory to strip) + -- We need to run configure and make install + print("Compiling Chez Scheme from source...") + + -- Configure with install prefix + local configure_cmd = "cd " .. root_path .. " && ./configure --installprefix=" .. root_path + print("Running: " .. configure_cmd) + local result = os.execute(configure_cmd) + if result ~= 0 and result ~= true then + error("Configure failed") + end + + -- Build + local make_cmd = "cd " .. root_path .. " && make" + print("Running: make") + result = os.execute(make_cmd) + if result ~= 0 and result ~= true then + error("Make failed") + end + + -- Install to the prefix directory + local install_cmd = "cd " .. root_path .. " && make install" + print("Running: make install") + result = os.execute(install_cmd) + if result ~= 0 and result ~= true then + error("Make install failed") + end + + -- Clean up build artifacts to save space (optional) + os.execute("cd " .. root_path .. " && rm -rf boot c examples mats s unicode workarea Makefile configure LOG NOTICE 2>/dev/null") + + print("Chez Scheme compilation complete!") +end diff --git a/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/pre_install.lua new file mode 100644 index 0000000000..11ec2d8cec --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chezscheme/hooks/pre_install.lua @@ -0,0 +1,16 @@ +--- Called before installation to return the download URL. +--- Chez Scheme only provides source tarballs, which need to be compiled. +--- @param ctx table +--- @field ctx.version string Version to install +--- @return table File info with URL +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + -- Source tarball URL pattern: csv{version}.tar.gz + local url = "https://github.com/cisco/ChezScheme/releases/download/v" .. version .. "/csv" .. version .. ".tar.gz" + + return { + url = url, + version = version + } +end diff --git a/crates/vfox/embedded-plugins/vfox-chezscheme/metadata.lua b/crates/vfox/embedded-plugins/vfox-chezscheme/metadata.lua new file mode 100644 index 0000000000..5378d3f003 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chezscheme/metadata.lua @@ -0,0 +1,9 @@ +PLUGIN = {} + +PLUGIN.name = "chezscheme" +PLUGIN.version = "0.1.0" +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-chezscheme" +PLUGIN.license = "MIT" +PLUGIN.description = "Chez Scheme - a programming language and implementation" +PLUGIN.minRuntimeVersion = "0.3.0" +PLUGIN.notes = { "Compiles from source - requires C compiler (gcc/clang) and make" } diff --git a/crates/vfox/embedded-plugins/vfox-chicken b/crates/vfox/embedded-plugins/vfox-chicken deleted file mode 160000 index 85ce8f79ed..0000000000 --- a/crates/vfox/embedded-plugins/vfox-chicken +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 85ce8f79ed99057a3415627c94af28e49781feec diff --git a/crates/vfox/embedded-plugins/vfox-chicken/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-chicken/hooks/available.lua new file mode 100644 index 0000000000..2cbf3a78fb --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chicken/hooks/available.lua @@ -0,0 +1,52 @@ +--- Returns a list of available versions of CHICKEN +--- Fetches from foldling.org/dust/ and parses the tarball filenames + +function PLUGIN:Available(ctx) + local http = require("http") + local resp, err = http.get({ + url = "https://foldling.org/dust/" + }) + if err ~= nil then + error("Failed to fetch version list: " .. err) + end + if resp.status_code ~= 200 then + error("Failed to fetch version list: HTTP " .. resp.status_code) + end + + local versions = {} + local seen = {} + + -- Parse HTML for chicken tarballs: chicken-VERSION-ARCH-OS-VARIANT.tar.gz + -- Only match versioned releases, not "master" + for version in resp.body:gmatch('chicken%-([0-9]+%.[0-9]+%.[0-9]+)%-') do + if not seen[version] then + seen[version] = true + table.insert(versions, { + version = version, + }) + end + end + + -- Sort versions in descending order (newest first) + table.sort(versions, function(a, b) + local function parse_version(v) + local parts = {} + for num in v:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + return parts + end + local va = parse_version(a.version) + local vb = parse_version(b.version) + for i = 1, math.max(#va, #vb) do + local na = va[i] or 0 + local nb = vb[i] or 0 + if na ~= nb then + return na > nb + end + end + return false + end) + + return versions +end diff --git a/crates/vfox/embedded-plugins/vfox-chicken/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-chicken/hooks/env_keys.lua new file mode 100644 index 0000000000..9289141219 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chicken/hooks/env_keys.lua @@ -0,0 +1,27 @@ +--- Returns environment variables to set for CHICKEN +--- Sets PATH to include the bin directory and library paths + +function PLUGIN:EnvKeys(ctx) + local file = require("file") + local main_path = ctx.path + local lib_path = file.join_path(main_path, "lib") + + return { + { + key = "PATH", + value = file.join_path(main_path, "bin"), + }, + { + key = "CHICKEN_HOME", + value = main_path, + }, + { + key = "LD_LIBRARY_PATH", + value = lib_path, + }, + { + key = "DYLD_LIBRARY_PATH", + value = lib_path, + }, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-chicken/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-chicken/hooks/post_install.lua new file mode 100644 index 0000000000..4a835870da --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chicken/hooks/post_install.lua @@ -0,0 +1,47 @@ +--- Post-installation hook for CHICKEN +--- Fixes library paths for macOS binaries + +function PLUGIN:PostInstall(ctx) + local file = require("file") + local root_path = ctx.rootPath + local os_type = RUNTIME.osType + + -- On macOS, we need to fix up library paths using install_name_tool + if os_type == "darwin" then + local lib_path = file.join_path(root_path, "lib") + local bin_path = file.join_path(root_path, "bin") + local libchicken = file.join_path(lib_path, "libchicken.dylib") + + -- Create a shell script to fix library paths + local script = string.format([[ +#!/bin/bash +set -e +LIB="%s" +BIN="%s" + +# Fix the library's own id +install_name_tool -id "$LIB/libchicken.dylib" "$LIB/libchicken.dylib" 2>/dev/null || true + +# Fix all binaries +for bin in chicken csc csi chicken-install chicken-uninstall chicken-status chicken-profile chicken-do feathers; do + if [ -f "$BIN/$bin" ]; then + # Get the old library path (the xxx placeholder) + OLD_PATH=$(otool -L "$BIN/$bin" 2>/dev/null | grep libchicken | head -1 | awk '{print $1}') + if [ -n "$OLD_PATH" ]; then + install_name_tool -change "$OLD_PATH" "$LIB/libchicken.dylib" "$BIN/$bin" 2>/dev/null || true + fi + fi +done +]], lib_path, bin_path) + + -- Write and execute the script + local script_path = root_path .. "/fix_libs.sh" + local f = io.open(script_path, "w") + if f then + f:write(script) + f:close() + os.execute("chmod +x " .. script_path .. " && " .. script_path) + os.execute("rm -f " .. script_path) + end + end +end diff --git a/crates/vfox/embedded-plugins/vfox-chicken/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-chicken/hooks/pre_install.lua new file mode 100644 index 0000000000..0c82564611 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chicken/hooks/pre_install.lua @@ -0,0 +1,53 @@ +--- Returns information about the version to install +--- Constructs the download URL based on OS and architecture + +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + local os_type = RUNTIME.osType + local arch_type = RUNTIME.archType + + -- Map OS and arch to the filename components + -- Pattern: chicken-VERSION-ARCH-OS-VARIANT.tar.gz + local arch, os_name, variant + + if os_type == "darwin" then + if arch_type ~= "amd64" then + error("CHICKEN only has x86_64 binaries for macOS. ARM64 is not supported.") + end + arch = "x86_64" + os_name = "macosx" + variant = "macosx" + elseif os_type == "linux" then + if arch_type ~= "amd64" then + error("CHICKEN only has x86_64 binaries for Linux. ARM64 is not supported.") + end + arch = "x86_64" + os_name = "linux" + variant = "gnu" -- Use GNU libc version by default + elseif os_type == "freebsd" then + if arch_type ~= "amd64" then + error("CHICKEN only has amd64 binaries for FreeBSD.") + end + arch = "amd64" + os_name = "bsd" + variant = "freebsd" + elseif os_type == "openbsd" then + if arch_type ~= "amd64" then + error("CHICKEN only has amd64 binaries for OpenBSD.") + end + arch = "amd64" + os_name = "bsd" + variant = "openbsd" + else + error("Unsupported operating system: " .. os_type) + end + + local filename = string.format("chicken-%s-%s-%s-%s.tar.gz", version, arch, os_name, variant) + local url = "https://foldling.org/dust/" .. filename + + return { + version = version, + url = url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-chicken/metadata.lua b/crates/vfox/embedded-plugins/vfox-chicken/metadata.lua new file mode 100644 index 0000000000..a98f3b0ba6 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chicken/metadata.lua @@ -0,0 +1,12 @@ +--- Metadata for the CHICKEN Scheme plugin +--- CHICKEN is a compiler for the Scheme programming language +--- https://call-cc.org/ + +PLUGIN = { + name = "chicken", + version = "0.1.0", + description = "CHICKEN Scheme compiler", + homepage = "https://call-cc.org/", + license = "BSD", + minRuntimeVersion = "0.3.0", +} diff --git a/crates/vfox/embedded-plugins/vfox-chromedriver b/crates/vfox/embedded-plugins/vfox-chromedriver deleted file mode 160000 index a9328093c9..0000000000 --- a/crates/vfox/embedded-plugins/vfox-chromedriver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a9328093c94a7befb3cbf0af09e5a26ea447280e diff --git a/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/available.lua new file mode 100644 index 0000000000..5bad7ceddf --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/available.lua @@ -0,0 +1,40 @@ +--- Returns all available versions of chromedriver from Google's API +--- @param ctx table Context provided by vfox +--- @return table Available versions +function PLUGIN:Available(ctx) + local http = require("http") + local json = require("json") + + local result = {} + + local resp, err = http.get({ + url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json", + headers = { + ["Accept"] = "application/json", + } + }) + + if err ~= nil then + error("Failed to fetch versions: " .. err) + end + + if resp.status_code ~= 200 then + error("Failed to fetch versions, status: " .. resp.status_code) + end + + local data = json.decode(resp.body) + if data == nil or data.versions == nil then + return result + end + + -- Collect versions that have chromedriver downloads + for _, v in ipairs(data.versions) do + if v.downloads and v.downloads.chromedriver then + table.insert(result, { + version = v.version, + }) + end + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/env_keys.lua new file mode 100644 index 0000000000..cb716a448d --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/env_keys.lua @@ -0,0 +1,14 @@ +--- Returns environment keys and paths for the installed tool +--- @param ctx table Context provided by vfox +--- @return table Environment keys +function PLUGIN:EnvKeys(ctx) + local mainSdk = ctx.sdkInfo["chromedriver"] + local path = mainSdk.path + + return { + { + key = "PATH", + value = path .. "/bin", + }, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/post_install.lua new file mode 100644 index 0000000000..d565e5e468 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/post_install.lua @@ -0,0 +1,62 @@ +--- Installs chromedriver by moving binary to bin directory +--- @param ctx table Context provided by vfox +function PLUGIN:PostInstall(ctx) + local cmd = require("cmd") + + local sdkInfo = ctx.sdkInfo["chromedriver"] + local path = sdkInfo.path + local version = sdkInfo.version + + -- Create bin directory + cmd.exec("mkdir -p '" .. path .. "/bin'") + + -- Determine platform suffix for the extracted directory using RUNTIME global + local osType = RUNTIME.osType + local archType = RUNTIME.archType + local platform = "" + + if osType == "darwin" then + if archType == "arm64" then + platform = "mac-arm64" + else + platform = "mac-x64" + end + elseif osType == "linux" then + platform = "linux64" + elseif osType == "windows" then + if archType == "amd64" or archType == "x86_64" then + platform = "win64" + else + platform = "win32" + end + end + + -- The zip extracts to chromedriver-{platform}/ + local srcDir = path .. "/chromedriver-" .. platform + + -- Check if srcDir exists, if not try without subdirectory + local file = io.open(srcDir .. "/chromedriver", "r") + if file then + file:close() + else + -- Try direct path (files extracted directly) + srcDir = path + end + + -- Copy chromedriver binary + if osType == "windows" then + cmd.exec("cp -f '" .. srcDir .. "/chromedriver.exe' '" .. path .. "/bin/'") + else + cmd.exec("cp -f '" .. srcDir .. "/chromedriver' '" .. path .. "/bin/'") + cmd.exec("chmod +x '" .. path .. "/bin/chromedriver'") + end + + -- Verify installation + local binaryName = osType == "windows" and "chromedriver.exe" or "chromedriver" + local verifyFile = io.open(path .. "/bin/" .. binaryName, "r") + if verifyFile then + verifyFile:close() + else + error("Failed to install chromedriver - binary not found at " .. path .. "/bin/" .. binaryName) + end +end diff --git a/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/pre_install.lua new file mode 100644 index 0000000000..b23be2e25a --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chromedriver/hooks/pre_install.lua @@ -0,0 +1,80 @@ +--- Returns version information for installation +--- @param ctx table Context provided by vfox (contains version) +--- @return table Version info with download URL +function PLUGIN:PreInstall(ctx) + local http = require("http") + local json = require("json") + + local version = ctx.version + + if version == nil or version == "" then + error("You must provide a version number, eg: vfox install chromedriver@131.0.6778.0") + end + + -- Determine platform using RUNTIME global + local osType = RUNTIME.osType + local archType = RUNTIME.archType + local platform = "" + + if osType == "darwin" then + if archType == "arm64" then + platform = "mac-arm64" + else + platform = "mac-x64" + end + elseif osType == "linux" then + platform = "linux64" + elseif osType == "windows" then + if archType == "amd64" or archType == "x86_64" then + platform = "win64" + else + platform = "win32" + end + else + error("Unsupported OS: " .. osType) + end + + -- Fetch the versions JSON to get the download URL + local resp, err = http.get({ + url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json", + headers = { + ["Accept"] = "application/json", + } + }) + + if err ~= nil then + error("Failed to fetch versions: " .. err) + end + + if resp.status_code ~= 200 then + error("Failed to fetch versions, status: " .. resp.status_code) + end + + local data = json.decode(resp.body) + if data == nil or data.versions == nil then + error("Failed to parse versions JSON") + end + + -- Find the version and platform URL + local downloadUrl = nil + for _, v in ipairs(data.versions) do + if v.version == version and v.downloads and v.downloads.chromedriver then + for _, d in ipairs(v.downloads.chromedriver) do + if d.platform == platform then + downloadUrl = d.url + break + end + end + break + end + end + + if downloadUrl == nil then + error("Could not find chromedriver " .. version .. " for platform " .. platform) + end + + return { + version = version, + url = downloadUrl, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-chromedriver/metadata.lua b/crates/vfox/embedded-plugins/vfox-chromedriver/metadata.lua new file mode 100644 index 0000000000..4a3794aad9 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-chromedriver/metadata.lua @@ -0,0 +1,11 @@ +--- Plugin metadata +PLUGIN = {} + +PLUGIN.name = "chromedriver" +PLUGIN.version = "0.1.0" +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-chromedriver" +PLUGIN.license = "Apache-2.0" +PLUGIN.description = "ChromeDriver - WebDriver for Chrome" + +--- Minimum vfox version required +PLUGIN.minRuntimeVersion = "0.3.0" diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse b/crates/vfox/embedded-plugins/vfox-clickhouse deleted file mode 160000 index 8789bfa0a1..0000000000 --- a/crates/vfox/embedded-plugins/vfox-clickhouse +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8789bfa0a1a0997120e81f95c2ed8efe3efc0524 diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/available.lua new file mode 100644 index 0000000000..c7713af698 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/available.lua @@ -0,0 +1,18 @@ +--- Returns all available versions of clickhouse from GitHub releases +--- @param ctx table Context object (unused for this plugin) +--- @return table Array of version objects with 'version' field +function PLUGIN:Available(ctx) + local util = require("util") + local versions = util.get_versions() + + -- Sort versions (newest first) + table.sort(versions, util.version_compare) + + -- Convert to vfox format + local result = {} + for _, v in ipairs(versions) do + table.insert(result, { version = v }) + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/env_keys.lua new file mode 100644 index 0000000000..dde6c264a8 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/env_keys.lua @@ -0,0 +1,12 @@ +--- Each SDK may have different environment variable configurations. +--- This allows plugins to define custom environment variables (including PATH settings) +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +function PLUGIN:EnvKeys(ctx) + return { + { + key = "PATH", + value = ctx.path .. "/bin" + } + } +end diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/post_install.lua new file mode 100644 index 0000000000..f914553c79 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/post_install.lua @@ -0,0 +1,87 @@ +--- Extension point, called after PreInstall, sets up clickhouse binary +--- @param ctx table +--- @field ctx.rootPath string SDK installation directory +function PLUGIN:PostInstall(ctx) + local rootPath = ctx.rootPath + local binDir = rootPath .. "/bin" + + -- Create bin directory + os.execute(string.format('mkdir -p "%s"', binDir)) + + if OS_TYPE == "darwin" then + -- macOS: single binary file was downloaded + -- Find the downloaded binary (clickhouse-macos or clickhouse-macos-aarch64) + local find_cmd = string.format('ls "%s"/clickhouse-macos* 2>/dev/null | head -1', rootPath) + local handle = io.popen(find_cmd) + if not handle then + error("Failed to find clickhouse binary") + end + local binary_path = handle:read("*l") + handle:close() + + if not binary_path or binary_path == "" then + error("Could not find clickhouse-macos binary in " .. rootPath) + end + + -- Move and rename to bin/clickhouse + local move_cmd = string.format('mv "%s" "%s/clickhouse"', binary_path, binDir) + local result = os.execute(move_cmd) + if not result then + error("Failed to move clickhouse binary") + end + + -- Make executable and remove quarantine + os.execute(string.format('chmod +x "%s/clickhouse"', binDir)) + os.execute(string.format('xattr -d com.apple.quarantine "%s/clickhouse" 2>/dev/null || true', binDir)) + else + -- Linux: tarball was extracted + -- The tarball extracts to usr/bin/clickhouse + local src_binary = rootPath .. "/usr/bin/clickhouse" + + -- Check if binary exists at expected location + local check_cmd = string.format('test -f "%s"', src_binary) + if not os.execute(check_cmd) then + -- Try alternate location + src_binary = rootPath .. "/clickhouse" + check_cmd = string.format('test -f "%s"', src_binary) + if not os.execute(check_cmd) then + error("Could not find clickhouse binary after extraction") + end + end + + -- Move binary to bin/ + local move_cmd = string.format('mv "%s" "%s/clickhouse"', src_binary, binDir) + local result = os.execute(move_cmd) + if not result then + -- Try copying instead + move_cmd = string.format('cp "%s" "%s/clickhouse"', src_binary, binDir) + result = os.execute(move_cmd) + if not result then + error("Failed to copy clickhouse binary to bin/") + end + end + + -- Make executable + os.execute(string.format('chmod +x "%s/clickhouse"', binDir)) + + -- Clean up extracted directories + os.execute(string.format('rm -rf "%s/usr" "%s/install" "%s/etc" 2>/dev/null || true', rootPath, rootPath, rootPath)) + end + + -- Create symlinks for clickhouse subcommands + local symlinks = { + "clickhouse-client", + "clickhouse-server", + "clickhouse-local", + "clickhouse-benchmark", + "clickhouse-compressor", + "clickhouse-format", + "clickhouse-obfuscator", + } + + for _, link in ipairs(symlinks) do + os.execute(string.format('ln -sf clickhouse "%s/%s" 2>/dev/null || true', binDir, link)) + end + + print("ClickHouse installed successfully!") +end diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/pre_install.lua new file mode 100644 index 0000000000..e05d163b2b --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-clickhouse/hooks/pre_install.lua @@ -0,0 +1,39 @@ +--- Returns information about where to download clickhouse +--- @param ctx table Context containing version info +--- @field ctx.version string The version to install +--- @return table Installation info including download URL +function PLUGIN:PreInstall(ctx) + local util = require("util") + local version = ctx.version + local arch = util.get_arch() + local trimmed_version = util.trim_version_suffix(version) + local url + + if OS_TYPE == "darwin" then + -- macOS: single binary file + -- clickhouse-macos (x86_64) or clickhouse-macos-aarch64 (arm64) + if arch == "arm64" then + url = string.format( + "https://github.com/ClickHouse/ClickHouse/releases/download/v%s/clickhouse-macos-aarch64", + version + ) + else + url = string.format( + "https://github.com/ClickHouse/ClickHouse/releases/download/v%s/clickhouse-macos", + version + ) + end + else + -- Linux: tarball + -- clickhouse-common-static-{trimmed_version}-{arch}.tgz + url = string.format( + "https://github.com/ClickHouse/ClickHouse/releases/download/v%s/clickhouse-common-static-%s-%s.tgz", + version, trimmed_version, arch + ) + end + + return { + version = version, + url = url, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse/lib/util.lua b/crates/vfox/embedded-plugins/vfox-clickhouse/lib/util.lua new file mode 100644 index 0000000000..f7c4aead83 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-clickhouse/lib/util.lua @@ -0,0 +1,96 @@ +--- Utility functions for the clickhouse vfox plugin + +local util = {} + +--- Fetch content from a URL using curl +--- @param url string The URL to fetch +--- @return string|nil content The response body or nil on error +function util.fetch(url) + local handle = io.popen(string.format('curl -sfL "%s"', url)) + if not handle then + return nil + end + local content = handle:read("*a") + handle:close() + if content == "" then + return nil + end + return content +end + +--- Get all version tags from GitHub releases (only lts and stable) +--- @return table versions List of version strings +function util.get_versions() + local versions = {} + local url = "https://api.github.com/repos/ClickHouse/ClickHouse/releases?per_page=100" + local content = util.fetch(url) + if not content then + return versions + end + + -- Parse JSON to extract tag names (versions) + for tag in content:gmatch('"tag_name"%s*:%s*"v([^"]+)"') do + -- Only include lts and stable releases + if tag:match("%-lts$") or tag:match("%-stable$") then + table.insert(versions, tag) + end + end + + return versions +end + +--- Compare version strings for sorting (descending - newest first) +--- @param a string First version +--- @param b string Second version +--- @return boolean true if a > b +function util.version_compare(a, b) + local function parse_version(v) + local parts = {} + for num in v:gmatch("(%d+)") do + table.insert(parts, tonumber(num)) + end + return parts + end + + local pa = parse_version(a) + local pb = parse_version(b) + + for i = 1, math.max(#pa, #pb) do + local na = pa[i] or 0 + local nb = pb[i] or 0 + if na ~= nb then + return na > nb + end + end + return false +end + +--- Get architecture string +--- @return string arch Architecture (amd64 or arm64) +function util.get_arch() + local handle = io.popen("uname -m") + if not handle then + return "amd64" + end + local arch = handle:read("*l") + handle:close() + + if arch == "x86_64" or arch == "amd64" then + return "amd64" + elseif arch == "aarch64" or arch == "arm64" then + return "arm64" + end + return "amd64" +end + +--- Trim version suffix (remove -lts, -stable, -prestable) +--- @param version string The version string +--- @return string trimmed The trimmed version +function util.trim_version_suffix(version) + local trimmed = version:gsub("%-lts$", "") + trimmed = trimmed:gsub("%-stable$", "") + trimmed = trimmed:gsub("%-prestable$", "") + return trimmed +end + +return util diff --git a/crates/vfox/embedded-plugins/vfox-clickhouse/metadata.lua b/crates/vfox/embedded-plugins/vfox-clickhouse/metadata.lua new file mode 100644 index 0000000000..a3bc595b17 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-clickhouse/metadata.lua @@ -0,0 +1,26 @@ +--- Plugin metadata for mise/vfox integration +PLUGIN = {} + +--- Plugin name +PLUGIN.name = "clickhouse" + +--- Plugin version (SemVer) +PLUGIN.version = "0.1.0" + +--- Plugin description +PLUGIN.description = "ClickHouse - fast open-source column-oriented database management system" + +--- Minimum vfox version required +PLUGIN.minRuntimeVersion = "0.3.0" + +--- Repository URL +PLUGIN.repository = "https://github.com/mise-plugins/vfox-clickhouse" + +--- Tool homepage +PLUGIN.homepage = "https://clickhouse.com" + +--- License +PLUGIN.license = "Apache-2.0" + +--- Notes about this plugin +PLUGIN.notes = "Installs the ClickHouse server and client binaries." diff --git a/crates/vfox/embedded-plugins/vfox-gcloud b/crates/vfox/embedded-plugins/vfox-gcloud deleted file mode 160000 index a7a4355e67..0000000000 --- a/crates/vfox/embedded-plugins/vfox-gcloud +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a7a4355e678d8ae1e283efeaaba61a1226b28dbc diff --git a/crates/vfox/embedded-plugins/vfox-gcloud/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/available.lua new file mode 100644 index 0000000000..97cd5d4883 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/available.lua @@ -0,0 +1,102 @@ +--- Return all available versions provided by this plugin +--- @param ctx table Empty table used as context, for future extension +--- @return table Descriptions of available versions and accompanying tool descriptions + +local http = require("http") +local json = require("json") + +-- GCS bucket configuration +local GCS_BUCKET = "cloud-sdk-release" +local GCS_PREFIX = "google-cloud-sdk" +local GCS_API_URL = "https://storage.googleapis.com/storage/v1/b/" .. GCS_BUCKET .. "/o" + +-- Cache for versions +local available_versions = nil + +--- Fetch versions from GCS with pagination +local function fetch_versions() + local versions = {} + local seen = {} + local page_token = nil + + repeat + -- Build URL with query parameters + local url = GCS_API_URL .. "?prefix=" .. GCS_PREFIX .. "&fields=kind,nextPageToken,items(name)" + if page_token then + url = url .. "&pageToken=" .. page_token + end + + -- Fetch page + local resp, err = http.get({ + url = url, + }) + + if err ~= nil or resp.status_code ~= 200 then + error("Failed to fetch versions from GCS: " .. (err or "status " .. resp.status_code)) + end + + local data = json.decode(resp.body) + + -- Extract versions from object names + -- Pattern: google-cloud-sdk-{version}-linux-x86_64.tar.gz + for _, item in ipairs(data.items or {}) do + local name = item.name + local version = string.match(name, "^google%-cloud%-sdk%-([%d%.]+)%-linux%-x86_64%.tar%.gz$") + if version and not seen[version] then + seen[version] = true + table.insert(versions, version) + end + end + + page_token = data.nextPageToken + until page_token == nil + + return versions +end + +--- Compare version strings for sorting +local function compare_versions(a, b) + local function parse_version(v) + local parts = {} + for part in string.gmatch(v, "([^%.]+)") do + table.insert(parts, tonumber(part) or 0) + end + return parts + end + + local va = parse_version(a) + local vb = parse_version(b) + + for i = 1, math.max(#va, #vb) do + local na = va[i] or 0 + local nb = vb[i] or 0 + if na ~= nb then + return na < nb + end + end + return false +end + +function PLUGIN:Available(ctx) + -- Use cached versions if available + if available_versions ~= nil then + return available_versions + end + + local versions = fetch_versions() + + -- Sort versions in ascending order + table.sort(versions, compare_versions) + + -- Build result table + local result = {} + for _, version in ipairs(versions) do + table.insert(result, { + version = version, + note = "", + }) + end + + available_versions = result + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-gcloud/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/env_keys.lua new file mode 100644 index 0000000000..74754dd272 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/env_keys.lua @@ -0,0 +1,24 @@ +--- Return environment variables for the tool +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +--- @return table Environment variables + +local file = require("file") + +function PLUGIN:EnvKeys(ctx) + local version_path = ctx.path + + -- The SDK extracts directly to the version path + local bin_path = file.join_path(version_path, "bin") + + return { + { + key = "PATH", + value = bin_path, + }, + { + key = "CLOUDSDK_ROOT_DIR", + value = version_path, + }, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-gcloud/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/post_install.lua new file mode 100644 index 0000000000..383255611f --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/post_install.lua @@ -0,0 +1,80 @@ +--- Called after the tool is installed +--- @param ctx table Context information +--- @field ctx.rootPath string The installation directory + +local file = require("file") + +--- Compare version strings +--- Returns true if v1 >= v2 +local function version_gte(v1, v2) + local function parse_version(v) + local parts = {} + for part in string.gmatch(v, "([^%.]+)") do + table.insert(parts, tonumber(part) or 0) + end + return parts + end + + local va = parse_version(v1) + local vb = parse_version(v2) + + for i = 1, math.max(#va, #vb) do + local na = va[i] or 0 + local nb = vb[i] or 0 + if na > nb then + return true + elseif na < nb then + return false + end + end + return true +end + +function PLUGIN:PostInstall(ctx) + local root_path = ctx.rootPath + local version = ctx.version or "" + + -- The SDK extracts directly to the root path + local sdk_path = root_path + local install_script = file.join_path(sdk_path, "install.sh") + + -- Check if install script exists + if not file.exists(install_script) then + -- On Windows, use install.bat + if RUNTIME.osType == "windows" or RUNTIME.osType == "Windows" then + install_script = file.join_path(sdk_path, "install.bat") + end + end + + if not file.exists(install_script) then + -- Some versions might not have an install script, skip silently + return + end + + -- Build install command arguments + local args = { + "--usage-reporting", "false", + "--path-update", "false", + "--quiet", + } + + -- For versions >= 352.0.0, disable Python installation + -- (gcloud bundles its own Python in newer versions) + if version ~= "" and version_gte(version, "352.0.0") then + table.insert(args, "--install-python") + table.insert(args, "false") + end + + -- Run the install script + local cmd_str + if RUNTIME.osType == "windows" or RUNTIME.osType == "Windows" then + cmd_str = '"' .. install_script .. '" ' .. table.concat(args, " ") + else + cmd_str = 'sh "' .. install_script .. '" ' .. table.concat(args, " ") + end + + local status = os.execute(cmd_str) + if status ~= 0 and status ~= true then + error("Failed to run gcloud install script") + end +end diff --git a/crates/vfox/embedded-plugins/vfox-gcloud/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/pre_install.lua new file mode 100644 index 0000000000..ad6aa13d57 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-gcloud/hooks/pre_install.lua @@ -0,0 +1,115 @@ +--- Return the pre-installation information including download URL +--- @param ctx table Context information +--- @field ctx.version string Version to install +--- @return table Version information with download URL + +local http = require("http") + +-- GCS bucket configuration +local GCS_BUCKET = "cloud-sdk-release" +local BASE_URL = "https://storage.googleapis.com/" .. GCS_BUCKET + +--- Get OS name for download URL +local function get_os_name() + local os_type = RUNTIME.osType + if os_type == "darwin" or os_type == "Darwin" then + return "darwin" + elseif os_type == "linux" or os_type == "Linux" then + return "linux" + elseif os_type == "windows" or os_type == "Windows" then + return "windows" + else + error("Unsupported operating system: " .. os_type) + end +end + +--- Get architecture name for download URL +local function get_arch_name() + local arch_type = RUNTIME.archType + local os_name = get_os_name() + + if arch_type == "amd64" or arch_type == "x86_64" then + return "x86_64" + elseif arch_type == "arm64" or arch_type == "aarch64" then + -- macOS uses arm64, Linux uses aarch64 + if os_name == "darwin" then + return "arm" + else + return "arm" + end + elseif arch_type == "386" or arch_type == "x86" then + return "x86" + else + error("Unsupported architecture: " .. arch_type) + end +end + +--- Get file extension based on OS +local function get_extension() + local os_name = get_os_name() + if os_name == "windows" then + return ".zip" + else + return ".tar.gz" + end +end + +--- Build the download filename +local function build_filename(version) + local os_name = get_os_name() + local arch_name = get_arch_name() + local ext = get_extension() + + -- Format: google-cloud-sdk-{version}-{os}-{arch}.tar.gz + -- For bundled Python (recommended): google-cloud-sdk-{version}-{os}-{arch}-bundled-python.tar.gz + return "google-cloud-sdk-" .. version .. "-" .. os_name .. "-" .. arch_name .. ext +end + +--- Fetch SHA256 checksum for the file +local function fetch_checksum(filename) + -- Google provides checksums at a .sha256 file + local checksum_url = BASE_URL .. "/" .. filename .. ".sha256" + + local resp, err = http.get({ + url = checksum_url, + }) + + if err ~= nil or resp.status_code ~= 200 then + -- Checksum file might not exist for all versions + return nil + end + + -- The file contains just the hash + local hash = string.match(resp.body, "^(%x+)") + return hash +end + +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + local filename = build_filename(version) + local url = BASE_URL .. "/" .. filename + + -- Verify the file exists + local resp, err = http.head({ + url = url, + }) + + if err ~= nil or resp.status_code == 404 then + error("Version " .. version .. " not found for this platform. URL: " .. url) + end + + -- Try to fetch checksum + local checksum = fetch_checksum(filename) + + local result = { + version = version, + url = url, + } + + if checksum then + result.sha256 = checksum + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-gcloud/metadata.lua b/crates/vfox/embedded-plugins/vfox-gcloud/metadata.lua new file mode 100644 index 0000000000..949a3dc72e --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-gcloud/metadata.lua @@ -0,0 +1,26 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "gcloud" +--- Plugin version +PLUGIN.version = "0.1.0" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/mise-plugins/vfox-gcloud" +--- Plugin license +PLUGIN.license = "MIT" +--- Plugin description +PLUGIN.description = "Google Cloud SDK (gcloud CLI)" + +--- !!! OPTIONAL !!! +--- Minimum compatible vfox version +PLUGIN.minRuntimeVersion = "0.3.0" +--- Some things that need user attention +PLUGIN.notes = { + "After installation, you may need to run 'gcloud init' to configure your account.", + "Additional components can be installed with 'gcloud components install '.", +} + +--- Legacy configuration filenames for determining tool version +PLUGIN.legacyFilenames = {} diff --git a/crates/vfox/embedded-plugins/vfox-semver/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-semver/hooks/available.lua new file mode 100644 index 0000000000..d6dbc369d3 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-semver/hooks/available.lua @@ -0,0 +1,47 @@ +-- hooks/available.lua +function PLUGIN:Available(ctx) + local http = require("http") + local json = require("json") + + -- GitHub API URL for releases + local repo_url = "https://api.github.com/repos/fsaintjacques/semver-tool/tags" + + -- Prepare headers + local headers = {} + if os.getenv("GITHUB_TOKEN") then + headers["Authorization"] = "token " .. os.getenv("GITHUB_TOKEN") + elseif os.getenv("GITHUB_API_TOKEN") then + headers["Authorization"] = "token " .. os.getenv("GITHUB_API_TOKEN") + end + + -- Make API request + local resp, err = http.get({ + url = repo_url, + headers = headers, + }) + + if err ~= nil then + error("Failed to fetch versions: " .. err) + end + + if resp.status_code ~= 200 then + error("GitHub API returned status " .. resp.status_code .. ": " .. resp.body) + end + + -- Parse response + local tags = json.decode(resp.body) + local result = {} + + -- Convert tags to versions + for i, tag_info in ipairs(tags) do + local version = tag_info.name + + -- Add version to result + table.insert(result, { + version = version, + note = nil, + }) + end + + return result +end diff --git a/crates/vfox/embedded-plugins/vfox-semver/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-semver/hooks/env_keys.lua new file mode 100644 index 0000000000..b1b0fcce82 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-semver/hooks/env_keys.lua @@ -0,0 +1,12 @@ +-- hooks/env_keys.lua +function PLUGIN:EnvKeys(ctx) + local mainPath = ctx.path + + -- Add the bin directory to PATH where semver will be installed + return { + { + key = "PATH", + value = mainPath .. "/bin", + }, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-semver/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-semver/hooks/post_install.lua new file mode 100644 index 0000000000..d0694e427a --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-semver/hooks/post_install.lua @@ -0,0 +1,25 @@ +-- hooks/post_install.lua +function PLUGIN:PostInstall(ctx) + local sdkInfo = ctx.sdkInfo["semver"] + local path = sdkInfo.path + + -- Create bin directory if it doesn't exist + os.execute("mkdir -p " .. path .. "/bin") + + -- Move the downloaded semver file to bin directory + local srcFile = path .. "/semver" + local destFile = path .. "/bin/semver" + + -- Move and make executable + local result = os.execute("mv " .. srcFile .. " " .. destFile .. " && chmod +x " .. destFile) + + if result ~= 0 then + error("Failed to install semver binary") + end + + -- Test that it works + local testResult = os.execute(destFile .. " --version > /dev/null 2>&1") + if testResult ~= 0 then + error("semver installation appears to be broken") + end +end diff --git a/crates/vfox/embedded-plugins/vfox-semver/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-semver/hooks/pre_install.lua new file mode 100644 index 0000000000..af72aa2fd6 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-semver/hooks/pre_install.lua @@ -0,0 +1,13 @@ +-- hooks/pre_install.lua +function PLUGIN:PreInstall(ctx) + local version = ctx.version + + -- The semver tool is a single script file downloaded from the GitHub repo + local url = "https://raw.githubusercontent.com/fsaintjacques/semver-tool/" .. version .. "/src/semver" + + return { + version = version, + url = url, + note = "Downloading semver " .. version, + } +end diff --git a/crates/vfox/embedded-plugins/vfox-semver/metadata.lua b/crates/vfox/embedded-plugins/vfox-semver/metadata.lua new file mode 100644 index 0000000000..6ca55f2496 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-semver/metadata.lua @@ -0,0 +1,9 @@ +-- metadata.lua +PLUGIN = { -- luacheck: ignore + name = "semver", + version = "1.0.0", + description = "A semantic versioning (semver) command-line tool", + author = "mise-plugins", + updateUrl = "https://github.com/mise-plugins/mise-semver", + minRuntimeVersion = "0.2.0", +} diff --git a/crates/vfox/embedded-plugins/vfox-vlang b/crates/vfox/embedded-plugins/vfox-vlang deleted file mode 160000 index 61dee71718..0000000000 --- a/crates/vfox/embedded-plugins/vfox-vlang +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 61dee71718b40c42314220cf03a34977c341d18c diff --git a/crates/vfox/embedded-plugins/vfox-vlang/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-vlang/hooks/available.lua new file mode 100644 index 0000000000..77287a5670 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/hooks/available.lua @@ -0,0 +1,8 @@ +local util = require("util") + +--- Return all available versions provided by this plugin +--- @param ctx table Empty table used as context, for future extension +--- @return table Descriptions of available versions and accompanying tool descriptions +function PLUGIN:Available(ctx) + return util:getInfo() +end \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-vlang/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-vlang/hooks/env_keys.lua new file mode 100644 index 0000000000..3cab395a7a --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/hooks/env_keys.lua @@ -0,0 +1,15 @@ +--- Each SDK may have different environment variable configurations. +--- This allows plugins to define custom environment variables (including PATH settings) +--- Note: Be sure to distinguish between environment variable settings for different platforms! +--- @param ctx table Context information +--- @field ctx.path string SDK installation directory +function PLUGIN:EnvKeys(ctx) + local mainPath = ctx.path + return { + { + key = "PATH", + value = mainPath + } + } + +end \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-vlang/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-vlang/hooks/post_install.lua new file mode 100644 index 0000000000..aec3281c56 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/hooks/post_install.lua @@ -0,0 +1,6 @@ +--- Extension point, called after PreInstall, can perform additional operations, +--- such as file operations for the SDK installation directory or compile source code +--- Currently can be left unimplemented! +function PLUGIN:PostInstall(ctx) + -- do nothing +end \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_install.lua new file mode 100644 index 0000000000..4ee0958ca2 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_install.lua @@ -0,0 +1,18 @@ +local util = require("util") +--- Returns some pre-installed information, such as version number, download address, local files, etc. +--- If checksum is provided, vfox will automatically check it for you. +--- @param ctx table +--- @field ctx.version string User-input version +--- @return table Version information +function PLUGIN:PreInstall(ctx) + if #util.RELEASES == 0 then + self:Available(ctx) + end + local releases = util.RELEASES + for _, release in ipairs(releases) do + if release.version == ctx.version then + return release + end + end + return {} +end \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_use.lua b/crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_use.lua new file mode 100644 index 0000000000..44bad6b955 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/hooks/pre_use.lua @@ -0,0 +1,6 @@ +--- When user invoke `use` command, this function will be called to get the +--- valid version information. +--- @param ctx table Context information +function PLUGIN:PreUse(ctx) + --do nothing +end \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-vlang/lib/util.lua b/crates/vfox/embedded-plugins/vfox-vlang/lib/util.lua new file mode 100644 index 0000000000..2aff87ba3d --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/lib/util.lua @@ -0,0 +1,71 @@ +local http = require("http") +local json = require("json") +local util = {} + +util.__index = util +local utilSingleton = setmetatable({}, util) +utilSingleton.SOURCE_URL = "https://raw.githubusercontent.com/ahai-code/sdk-sources/main/v.json" +utilSingleton.RELEASES ={} + +function util:compare_versions(v1o, v2o) + local v1 = v1o.version + local v2 = v2o.version + local v1_parts = {} + for part in string.gmatch(v1, "[^.]+") do + table.insert(v1_parts, tonumber(part)) + end + + local v2_parts = {} + for part in string.gmatch(v2, "[^.]+") do + table.insert(v2_parts, tonumber(part)) + end + + for i = 1, math.max(#v1_parts, #v2_parts) do + local v1_part = v1_parts[i] or 0 + local v2_part = v2_parts[i] or 0 + if v1_part > v2_part then + return true + elseif v1_part < v2_part then + return false + end + end + + return false +end + +function util:getInfo() + local result = {} + local resp, err = http.get({ + url = utilSingleton.SOURCE_URL + }) + if err ~= nil then + error("Failed to get information: " .. err) + end + if resp.status_code ~= 200 then + error("Failed to get information: status_code =>" .. resp.status_code) + end + local respInfo = json.decode(resp.body)[RUNTIME.osType] + for version, array in pairs(respInfo) do + local url = "" + if string.sub(version, 1, #("weekly.")) == "weekly." then + version = string.gsub(version, "^weekly.", "") + end + + for _, obj in ipairs(array) do + if obj.Arch=="" then + url = obj.Url + elseif obj.Arch == RUNTIME.archType then + url = obj.Url + end + end + + table.insert(result, {version = version,note=""}) + table.insert(utilSingleton.RELEASES,{version = version,url=url}) + end + table.sort(result, function(a, b) + return util:compare_versions(a,b) + end) + return result +end + +return utilSingleton \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-vlang/metadata.lua b/crates/vfox/embedded-plugins/vfox-vlang/metadata.lua new file mode 100644 index 0000000000..1da808319b --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-vlang/metadata.lua @@ -0,0 +1,38 @@ +--- !!! DO NOT EDIT OR RENAME !!! +PLUGIN = {} + +--- !!! MUST BE SET !!! +--- Plugin name +PLUGIN.name = "vlang" +--- Plugin version +PLUGIN.version = "0.1.2" +--- Plugin homepage +PLUGIN.homepage = "https://github.com/ahai-code/vfox-vlang" +--- Plugin license, please choose a correct license according to your needs. +PLUGIN.license = "Apache 2.0" +--- Plugin description +PLUGIN.description = "Vlang plugin" + + +--- !!! OPTIONAL !!! +--[[ +NOTE: + Minimum compatible vfox version. + If the plugin is not compatible with the current vfox version, + vfox will not load the plugin and prompt the user to upgrade vfox. + --]] +PLUGIN.minRuntimeVersion = "0.3.2" +--[[ +NOTE: + If configured, vfox will check for updates to the plugin at this address, + otherwise it will check for updates at the global registry. + + If you want use the global registry to distribute your plugin, you can remove this field. + + If you develop a plugin based on the template, which will automatically generate a manifest file by CI, + you can set this address to the manifest file address, so that the plugin can be updated automatically. + + --]] +PLUGIN.manifestUrl = "https://github.com/version-fox/ahai-code/vfox-vlang/releases/download/manifest/manifest.json" +-- Some things that need user to be attention! +PLUGIN.notes = {} diff --git a/crates/vfox/embedded-plugins/vfox-yarn b/crates/vfox/embedded-plugins/vfox-yarn deleted file mode 160000 index 990635f054..0000000000 --- a/crates/vfox/embedded-plugins/vfox-yarn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 990635f054fba8fee71b7ae0be3a3c178426ec66 diff --git a/crates/vfox/embedded-plugins/vfox-yarn/hooks/available.lua b/crates/vfox/embedded-plugins/vfox-yarn/hooks/available.lua new file mode 100644 index 0000000000..a75f25a351 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/hooks/available.lua @@ -0,0 +1,117 @@ +--- List all available versions + +local function fetch_github_tags(repo_url) + -- Use git ls-remote to get tags + local cmd = 'git ls-remote --refs --tags "' .. repo_url .. '"' + + -- Detect Windows + local is_windows = package.config:sub(1,1) == '\\' + + -- Redirect stderr appropriately for the platform + if is_windows then + cmd = cmd .. " 2>NUL" + else + cmd = cmd .. " 2>/dev/null" + end + + local handle = io.popen(cmd) + if not handle then + return {} + end + + local result = handle:read("*a") + handle:close() + + -- If result is empty or nil, return empty table + if not result or result == "" then + return {} + end + + local tags = {} + for line in result:gmatch("[^\r\n]+") do + -- Extract tag name from refs/tags/... + local tag = line:match("refs/tags/(.+)$") + if tag then + table.insert(tags, tag) + end + end + + return tags +end + +local function version_compare(a, b) + -- Simple version comparison for sorting + local function parse_version(v) + local parts = {} + for part in string.gmatch(v, "[^%.]+") do + table.insert(parts, tonumber(part) or 0) + end + return parts + end + + local a_parts = parse_version(a) + local b_parts = parse_version(b) + + for i = 1, math.max(#a_parts, #b_parts) do + local a_val = a_parts[i] or 0 + local b_val = b_parts[i] or 0 + if a_val ~= b_val then + return a_val > b_val -- Descending order + end + end + + return false +end + +function PLUGIN:Available(ctx) + local versions = {} + + -- Get Yarn Berry versions (v2.x+) + local berry_tags = fetch_github_tags("https://github.com/yarnpkg/berry.git") + local berry_versions = {} + + for _, tag in ipairs(berry_tags) do + -- Extract version from @yarnpkg/cli/X.X.X format + local version = tag:match("@yarnpkg/cli/(.+)$") + if version then + table.insert(berry_versions, version) + end + end + + -- Sort Berry versions in descending order + table.sort(berry_versions, version_compare) + + -- Add Berry versions to the list + for _, version in ipairs(berry_versions) do + table.insert(versions, { + version = version + }) + end + + -- Get Yarn Classic versions (v1.x) + local classic_tags = fetch_github_tags("https://github.com/yarnpkg/yarn.git") + local classic_versions = {} + + for _, tag in ipairs(classic_tags) do + -- Remove 'v' prefix if present + local version = tag:match("^v(.+)$") or tag + -- Only include 1.x versions (exclude 0.x) + if version:match("^1%.") then + table.insert(classic_versions, version) + end + end + + -- Sort Classic versions in descending order + table.sort(classic_versions, version_compare) + + -- Add Classic versions to the list + for _, version in ipairs(classic_versions) do + table.insert(versions, { + version = version + }) + end + + return versions +end + +return PLUGIN \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-yarn/hooks/env_keys.lua b/crates/vfox/embedded-plugins/vfox-yarn/hooks/env_keys.lua new file mode 100644 index 0000000000..e2b7a713d3 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/hooks/env_keys.lua @@ -0,0 +1,16 @@ +--- Environment keys hook + +function PLUGIN:EnvKeys(ctx) + -- Get the SDK installation path + local version_path = ctx.path + + -- Return the PATH configuration for yarn binaries + return { + { + key = "PATH", + value = version_path .. "/bin" + } + } +end + +return PLUGIN \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-yarn/hooks/legacy_filenames.lua b/crates/vfox/embedded-plugins/vfox-yarn/hooks/legacy_filenames.lua new file mode 100644 index 0000000000..2a89cd54e1 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/hooks/legacy_filenames.lua @@ -0,0 +1,6 @@ +--- Get list of legacy filenames +return function(ctx) + return { + ".yvmrc" + } +end \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-yarn/hooks/parse_legacy_file.lua b/crates/vfox/embedded-plugins/vfox-yarn/hooks/parse_legacy_file.lua new file mode 100644 index 0000000000..f37df52c9e --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/hooks/parse_legacy_file.lua @@ -0,0 +1,19 @@ +--- Parse legacy version files + +function PLUGIN:ParseLegacyFile(ctx) + local filepath = ctx.filepath + local file = io.open(filepath, "r") + if file then + local version = file:read("*l") + file:close() + if version then + version = version:gsub("^v", ""):gsub("%s+", "") + return { + version = version + } + end + end + return {} +end + +return PLUGIN \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-yarn/hooks/post_install.lua b/crates/vfox/embedded-plugins/vfox-yarn/hooks/post_install.lua new file mode 100644 index 0000000000..32e6e00a30 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/hooks/post_install.lua @@ -0,0 +1,103 @@ +--- Post-installation hook + +local function download_file(url, output_path) + -- Detect Windows + local is_windows = package.config:sub(1,1) == '\\' + local stderr_redirect = is_windows and " 2>NUL" or " 2>/dev/null" + + -- Try curl first (more likely to be available on Windows via Git Bash) + local curl_cmd = "curl -sSL -o " .. output_path .. " " .. url .. stderr_redirect + local wget_cmd = "wget -q -O " .. output_path .. " " .. url .. stderr_redirect + + if os.execute(curl_cmd) == 0 then + return true + elseif os.execute(wget_cmd) == 0 then + return true + end + return false +end + +function PLUGIN:PostInstall(ctx) + -- Get install path - it should be in sdkInfo + local install_path = nil + local version = nil + + -- Try to get path from sdkInfo + if ctx.sdkInfo and ctx.sdkInfo.yarn then + install_path = ctx.sdkInfo.yarn.path + version = ctx.sdkInfo.yarn.version + end + + -- Fallback to environment variable + if not install_path then + install_path = os.getenv("MISE_INSTALL_PATH") + end + if not version then + version = os.getenv("MISE_INSTALL_VERSION") or ctx.version + end + + if not install_path or not version then + -- For v1, mise handles everything, so this is OK + return {} + end + + local major_version = string.sub(version, 1, 1) + + if major_version ~= "1" then + -- Yarn Berry (v2.x+) - download single JS file + local yarn_url = "https://repo.yarnpkg.com/" .. version .. "/packages/yarnpkg-cli/bin/yarn.js" + + -- Detect Windows + local is_windows = package.config:sub(1,1) == '\\' + + -- Create bin directory (cross-platform) + local bin_dir = install_path .. "/bin" + if is_windows then + os.execute('mkdir "' .. bin_dir .. '" 2>NUL') + else + os.execute("mkdir -p " .. bin_dir) + end + + -- Download yarn.js + local yarn_js_file = bin_dir .. "/yarn.js" + if not download_file(yarn_url, yarn_js_file) then + error("Failed to download Yarn v2+") + end + + -- Create wrapper script + if is_windows then + -- Create yarn.cmd wrapper for Windows + local yarn_cmd = bin_dir .. "/yarn.cmd" + local cmd_file = io.open(yarn_cmd, "w") + if cmd_file then + cmd_file:write("@echo off\n") + cmd_file:write('node "%~dp0yarn.js" %*\n') + cmd_file:close() + end + + -- Also create yarn without extension for Git Bash + local yarn_sh = bin_dir .. "/yarn" + local sh_file = io.open(yarn_sh, "w") + if sh_file then + sh_file:write("#!/bin/sh\n") + sh_file:write('exec node "$(dirname "$0")/yarn.js" "$@"\n') + sh_file:close() + end + else + -- Create shell wrapper for Unix + local yarn_file = bin_dir .. "/yarn" + local wrapper_file = io.open(yarn_file, "w") + if wrapper_file then + wrapper_file:write("#!/bin/sh\n") + wrapper_file:write('exec node "$(dirname "$0")/yarn.js" "$@"\n') + wrapper_file:close() + end + -- Make executable + os.execute("chmod +x " .. yarn_file) + end + end + + return {} +end + +return PLUGIN \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-yarn/hooks/pre_install.lua b/crates/vfox/embedded-plugins/vfox-yarn/hooks/pre_install.lua new file mode 100644 index 0000000000..cfe31916b1 --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/hooks/pre_install.lua @@ -0,0 +1,40 @@ +--- Pre-installation hook + +function PLUGIN:PreInstall(ctx) + local version = ctx.version + local major_version = string.sub(version, 1, 1) + + if major_version == "1" then + -- Yarn Classic (v1.x) - return tarball URL for mise to handle + local archive_url = "https://classic.yarnpkg.com/downloads/" .. version .. "/yarn-v" .. version .. ".tar.gz" + + -- Note about GPG verification (skip on Windows) + local is_windows = package.config:sub(1,1) == '\\' + if os.getenv("MISE_YARN_SKIP_GPG") == nil and not is_windows then + local stderr_redirect = " 2>/dev/null" + + local gpg_check = io.popen("command -v gpg" .. stderr_redirect) + local has_gpg = gpg_check and gpg_check:read("*a"):match("%S") + if gpg_check then gpg_check:close() end + + if not has_gpg then + print("⚠️ Note: GPG verification skipped (gpg not found). Set MISE_YARN_SKIP_GPG=1 to suppress this message") + end + -- Note: We can't do GPG verification when mise handles the download + -- This is a tradeoff for simpler code + end + + -- Return URL for mise to download and extract + return { + version = version, + url = archive_url + } + else + -- Yarn Berry (v2.x+) - single JS file, handled in post-install + return { + version = version + } + end +end + +return PLUGIN \ No newline at end of file diff --git a/crates/vfox/embedded-plugins/vfox-yarn/metadata.lua b/crates/vfox/embedded-plugins/vfox-yarn/metadata.lua new file mode 100644 index 0000000000..70822f907e --- /dev/null +++ b/crates/vfox/embedded-plugins/vfox-yarn/metadata.lua @@ -0,0 +1,18 @@ +--- Plugin metadata and configuration for Yarn +---@meta + +PLUGIN = { + name = "yarn", + author = "mise-plugins", + version = "0.1.0", + description = "Yarn package manager plugin for mise", + homepage = "https://github.com/mise-plugins/mise-yarn", + license = "MIT", + notes = [[ +This plugin installs Yarn package manager. +Supports both Yarn Classic (v1.x) and Yarn Berry (v2.x+). + ]], + minRuntimeVersion = "0.5.0" +} + +return PLUGIN \ No newline at end of file diff --git a/registry.toml b/registry.toml index 98cbfb6bd9..4e7d5658d8 100644 --- a/registry.toml +++ b/registry.toml @@ -3905,7 +3905,7 @@ description = "Semantic Tagging Script for Git" [tools.semver] backends = [ # "aqua:fsaintjacques/semver-tool", # see https://github.com/jdx/mise/discussions/5833 - "vfox:mise-plugins/mise-semver", + "vfox:mise-plugins/vfox-semver", "asdf:mathew-fleisch/asdf-semver", ] description = "semver bash implementation" diff --git a/xtasks/release-plz b/xtasks/release-plz index a2ca0ba5e6..09d03280ba 100755 --- a/xtasks/release-plz +++ b/xtasks/release-plz @@ -161,64 +161,30 @@ changelog="$(echo "$changelog" | tail -n +3)" mise up mise lock -# Update embedded vfox plugin submodules based on mise registry -# Tools where vfox is the first backend should have embedded plugins +# Update embedded vfox plugins (delete all and re-clone fresh, similar to aqua-registry) EMBEDDED_PLUGINS_DIR="crates/vfox/embedded-plugins" - -# Get current embedded plugins (submodule directory names) -CURRENT_EMBEDDED="" -if [[ -d $EMBEDDED_PLUGINS_DIR ]]; then - CURRENT_EMBEDDED="$(find "$EMBEDDED_PLUGINS_DIR" -maxdepth 1 -type d -name 'vfox-*' -exec basename {} \; | sort)" -fi - -# Get tools where vfox is the FIRST (default) backend using mise registry command -# Output format: "toolname backend1 backend2 ..." -# We only want tools where the first backend starts with "vfox:" -VFOX_REGISTRY="$(mise registry | awk '$2 ~ /^vfox:/ {print}')" - -# Extract just the plugin directory names (e.g., vfox-aapt2) for comparison -DESIRED_EMBEDDED="$(echo "$VFOX_REGISTRY" | awk '{print $2}' | sed 's|vfox:||' | sed 's|.*/||' | sort | uniq)" - -# Find plugins to add (in desired but not in current) -PLUGINS_TO_ADD="$(comm -23 <(echo "$DESIRED_EMBEDDED") <(echo "$CURRENT_EMBEDDED"))" - -# Find plugins to remove (in current but not in desired) -PLUGINS_TO_REMOVE="$(comm -13 <(echo "$DESIRED_EMBEDDED") <(echo "$CURRENT_EMBEDDED"))" - -# Add new submodules -if [[ -n $PLUGINS_TO_ADD ]]; then - echo "Adding embedded vfox plugins: $PLUGINS_TO_ADD" - while IFS= read -r plugin; do - [[ -z $plugin ]] && continue - # Extract the org/repo from mise registry output for this plugin - # Use pattern that matches plugin name at end of URL (followed by space or EOL) - repo_path="$(echo "$VFOX_REGISTRY" | grep -E "/$plugin( |\$)" | awk '{print $2}' | sed 's|vfox:||' | head -1)" - if [[ -n $repo_path ]]; then - echo "Adding submodule for $plugin from https://github.com/$repo_path" - git submodule add "https://github.com/$repo_path.git" "$EMBEDDED_PLUGINS_DIR/$plugin" || true - fi - done <<<"$PLUGINS_TO_ADD" -fi - -# Remove old submodules -if [[ -n $PLUGINS_TO_REMOVE ]]; then - echo "Removing embedded vfox plugins: $PLUGINS_TO_REMOVE" - while IFS= read -r plugin; do - [[ -z $plugin ]] && continue - echo "Removing submodule for $plugin" - git submodule deinit -f "$EMBEDDED_PLUGINS_DIR/$plugin" || true - git rm -f "$EMBEDDED_PLUGINS_DIR/$plugin" || true - rm -rf ".git/modules/$EMBEDDED_PLUGINS_DIR/$plugin" || true - done <<<"$PLUGINS_TO_REMOVE" -fi - -# Update existing submodules to latest -git submodule update --remote --merge "$EMBEDDED_PLUGINS_DIR" || true +rm -rf "$EMBEDDED_PLUGINS_DIR"/vfox-* + +# Clone all tools where vfox is the FIRST (default) backend +mise registry | awk '$2 ~ /^vfox:/ {print $2}' | sed 's|vfox:||' | sort -u | while read -r repo_path; do + plugin="$(basename "$repo_path")" + echo "Cloning $plugin from https://github.com/$repo_path" + TEMP_DIR="$(mktemp -d)" + git clone --depth 1 "https://github.com/$repo_path.git" "$TEMP_DIR" 2>&1 | grep -v "^Cloning" || true + DEST_DIR="$EMBEDDED_PLUGINS_DIR/$plugin" + mkdir -p "$DEST_DIR/hooks" + cp "$TEMP_DIR/metadata.lua" "$DEST_DIR/" + cp "$TEMP_DIR/hooks/"*.lua "$DEST_DIR/hooks/" 2>/dev/null || true + if [[ -d "$TEMP_DIR/lib" ]]; then + mkdir -p "$DEST_DIR/lib" + cp "$TEMP_DIR/lib/"*.lua "$DEST_DIR/lib/" 2>/dev/null || true + fi + rm -rf "$TEMP_DIR" +done git status # cargo update git add \ - .gitmodules \ Cargo.lock \ Cargo.toml \ CHANGELOG.md \