445 lines · 12.5 KB
---@brief [[
--- glaze.nvim update checker
--- Checks for newer versions of registered Go binaries
---@brief ]]

local M = {}

---@class GlazeUpdateInfo
---@field name string Binary name
---@field installed_version? string Currently installed version
---@field latest_version? string Latest available version
---@field has_update boolean Whether an update is available

---@type table<string, GlazeUpdateInfo>
M._update_info = {}

---@type boolean
M._checking = false

local STATE_FILE = vim.fn.stdpath("data") .. "/glaze/state.json"

---Parse a version string into comparable components.
---Handles semver (v1.2.3), pseudo-versions (v0.0.0-20240122...), etc.
---@param version string
---@return number[] parts, string? prerelease, number? pseudo_ts
local function parse_version(version)
  if not version then
    return {}, nil, nil
  end

  -- Strip leading 'v' and any build metadata (semver §10, e.g. +incompatible)
  local v = version:gsub("^v", ""):gsub("%+.*$", "")

  -- Detect the 14-digit timestamp embedded in any Go pseudo-version form
  -- (v0.0.0-<ts>-<hash>, vX.Y.Z-0.<ts>-<hash>, vX.Y.Z-pre.0.<ts>-<hash>).
  local pseudo_ts = v:match("(%d%d%d%d%d%d%d%d%d%d%d%d%d%d)%-%x+$")

  -- Split by hyphen to separate prerelease
  local base, prerelease = v:match("^([^-]+)-?(.*)$")
  if prerelease == "" then