From d97b27aa50e498a262e76e5d63d9763b607cb446 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:30:42 +0000 Subject: [PATCH 1/6] windows fixes --- .github/workflows/workflow.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index b6179b1..0670dc0 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -46,6 +46,19 @@ jobs: New-Item -ItemType Directory -Force -Path $pluginDir New-Item -ItemType Junction -Path "$pluginDir\yarn" -Target $PWD + # Validate version listing + - name: Validate mise ls-remote works + shell: bash + run: | + echo "Listing available yarn versions..." + mise ls-remote yarn | head -20 + echo "" + echo "Checking for v1 versions..." + mise ls-remote yarn | grep -E '^1\.' | head -5 || (echo "ERROR: No v1 versions found!" && exit 1) + echo "" + echo "Checking for v2+ versions..." + mise ls-remote yarn | grep -E '^[234]\.' | head -5 || (echo "ERROR: No v2+ versions found!" && exit 1) + # Test Yarn v1 (Classic) - name: Test Yarn v1 installation shell: bash From b090ee122268f67c65df474344c156b30cd84ec6 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:31:26 +0000 Subject: [PATCH 2/6] Fix Windows compatibility and add version validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrite available.lua to use pure Lua parsing instead of shell pipes - Remove dependency on sed, grep, and sort commands that fail on Windows - Add mise ls-remote validation step to GitHub Actions to verify versions are found - Implement proper version sorting in Lua for cross-platform compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- hooks/available.lua | 118 ++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 36 deletions(-) diff --git a/hooks/available.lua b/hooks/available.lua index d1637e2..b8c454b 100644 --- a/hooks/available.lua +++ b/hooks/available.lua @@ -1,55 +1,101 @@ --- List all available versions PLUGIN = {} -local function execCommand(cmd) +local function fetch_github_tags(repo_url) + -- Use git ls-remote to get tags + local cmd = 'git ls-remote --refs --tags "' .. repo_url .. '"' local handle = io.popen(cmd .. " 2>/dev/null") - if handle then - local result = handle:read("*a") - handle:close() - return result + if not handle then + return {} end - return "" + + local result = handle:read("*a") + handle:close() + + 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+) FIRST in DESCENDING order - -- When mise reverses the list, these will appear LAST in ASCENDING order - local berry_output = execCommand([[ - git ls-remote --refs --tags "https://github.com/yarnpkg/berry.git" | - grep '@yarnpkg/cli' | - sed -E 's|^.+refs/tags/@yarnpkg/cli/||g' | - sort -rV - ]]) - - for version in berry_output:gmatch("[^\n]+") do - if version and version ~= "" then - table.insert(versions, { - version = version - }) + -- 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 - -- Get Yarn Classic versions (v1.x) SECOND in DESCENDING order - -- When mise reverses the list, these will appear FIRST in ASCENDING order - local classic_output = execCommand([[ - git ls-remote --refs --tags "https://github.com/yarnpkg/yarn.git" | - sed -E 's|^.+refs/tags/||g' | - grep -E '^v' | - sed -E 's|^v||g' | - grep -Ev '^0\.' | - sort -rV - ]]) - - for version in classic_output:gmatch("[^\n]+") do - if version and version ~= "" then - table.insert(versions, { - version = version - }) + -- 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 From a148671ee52359b175dc5dff2f77a845b5376ad0 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:33:18 +0000 Subject: [PATCH 3/6] Fix Windows stderr redirection in available.lua MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use NUL instead of /dev/null for stderr redirection on Windows - Detect Windows platform using package.config - This fixes "The system cannot find the path specified" error on Windows 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- hooks/available.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hooks/available.lua b/hooks/available.lua index b8c454b..5520b0a 100644 --- a/hooks/available.lua +++ b/hooks/available.lua @@ -4,7 +4,18 @@ PLUGIN = {} local function fetch_github_tags(repo_url) -- Use git ls-remote to get tags local cmd = 'git ls-remote --refs --tags "' .. repo_url .. '"' - local handle = io.popen(cmd .. " 2>/dev/null") + + -- 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 @@ -12,6 +23,11 @@ local function fetch_github_tags(repo_url) 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/... From aaa0c1887b3b6e44d4a8b229e362d281327d5e7b Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:42:00 +0000 Subject: [PATCH 4/6] Fix Windows compatibility issues in installation hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix stderr redirection to use NUL on Windows instead of /dev/null - Use platform-specific mkdir commands (mkdir vs mkdir -p) - Skip chmod on Windows (not needed for JS files) - Skip GPG check on Windows entirely - Prefer curl over wget for better Windows Git Bash compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- hooks/post_install.lua | 34 ++++++++++++++++++++++++---------- hooks/pre_install.lua | 9 ++++++--- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/hooks/post_install.lua b/hooks/post_install.lua index 0870409..bbdc071 100644 --- a/hooks/post_install.lua +++ b/hooks/post_install.lua @@ -2,13 +2,17 @@ PLUGIN = {} local function download_file(url, output_path) - -- Try wget first, then curl - local wget_cmd = "wget -q -O " .. output_path .. " " .. url .. " 2>/dev/null" - local curl_cmd = "curl -sSL -o " .. output_path .. " " .. url .. " 2>/dev/null" + -- Detect Windows + local is_windows = package.config:sub(1,1) == '\\' + local stderr_redirect = is_windows and " 2>NUL" or " 2>/dev/null" - if os.execute(wget_cmd) == 0 then + -- 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(curl_cmd) == 0 then + elseif os.execute(wget_cmd) == 0 then return true end return false @@ -44,17 +48,27 @@ function PLUGIN:PostInstall(ctx) -- Yarn Berry (v2.x+) - download single JS file local yarn_url = "https://repo.yarnpkg.com/" .. version .. "/packages/yarnpkg-cli/bin/yarn.js" - -- Create bin directory - os.execute("mkdir -p " .. install_path .. "/bin") + -- 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_file = install_path .. "/bin/yarn" + local yarn_file = bin_dir .. "/yarn" if not download_file(yarn_url, yarn_file) then error("Failed to download Yarn v2+") end - -- Make executable - os.execute("chmod +x " .. yarn_file) + -- Make executable (Unix only, not needed on Windows) + if not is_windows then + os.execute("chmod +x " .. yarn_file) + end end return {} diff --git a/hooks/pre_install.lua b/hooks/pre_install.lua index 6f6b202..ea9152b 100644 --- a/hooks/pre_install.lua +++ b/hooks/pre_install.lua @@ -9,9 +9,12 @@ function PLUGIN:PreInstall(ctx) -- 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 - if os.getenv("MISE_YARN_SKIP_GPG") == nil then - local gpg_check = io.popen("command -v gpg 2>/dev/null") + -- 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 From 5255a3d7b9ef2ef770606ecf6a5bf21d1e43b1c4 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:45:57 +0000 Subject: [PATCH 5/6] Update metadata.lua repository fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change author from vfox-yarn contributors to mise-plugins - Update homepage to mise-plugins/mise-yarn repository - Update description to reference mise instead of vfox 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- metadata.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metadata.lua b/metadata.lua index 7312813..70822f9 100644 --- a/metadata.lua +++ b/metadata.lua @@ -3,10 +3,10 @@ PLUGIN = { name = "yarn", - author = "vfox-yarn contributors", + author = "mise-plugins", version = "0.1.0", - description = "Yarn package manager plugin for vfox", - homepage = "https://github.com/version-fox/vfox-yarn", + description = "Yarn package manager plugin for mise", + homepage = "https://github.com/mise-plugins/mise-yarn", license = "MIT", notes = [[ This plugin installs Yarn package manager. From 92a11ec01c8c46a54635ca785a9a9db6a9239f1e Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:47:40 +0000 Subject: [PATCH 6/6] Create proper wrapper scripts for Yarn v2+ on all platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Download yarn.js instead of yarn for v2+ - Create yarn.cmd wrapper for Windows CMD - Create shell wrapper script for Unix and Git Bash - Wrapper scripts properly invoke Node.js to run yarn.js This fixes the issue where Yarn v2+ wouldn't run on Windows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- hooks/post_install.lua | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/hooks/post_install.lua b/hooks/post_install.lua index bbdc071..ec319f0 100644 --- a/hooks/post_install.lua +++ b/hooks/post_install.lua @@ -60,13 +60,40 @@ function PLUGIN:PostInstall(ctx) end -- Download yarn.js - local yarn_file = bin_dir .. "/yarn" - if not download_file(yarn_url, yarn_file) then + 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 - -- Make executable (Unix only, not needed on Windows) - if not is_windows then + -- 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