yaziPlugins.updater: leverage nixpkgs-plugin-update (#519819)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "bypass.yazi";
|
||||
version = "25.3.2-unstable-2025-06-01";
|
||||
version = "0-unstable-2025-06-01";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Rolv-Apneseth";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "chmod.yazi";
|
||||
version = "26.1.22-unstable-2026-02-27";
|
||||
version = "0-unstable-2026-02-27";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "clipboard.yazi";
|
||||
version = "0-unstable-2026-04-24";
|
||||
version = "0-unstable-2026-05-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "XYenon";
|
||||
repo = "clipboard.yazi";
|
||||
rev = "d6fc53152a20aebad8dc6e2550940f7efe226838";
|
||||
hash = "sha256-6jlMzVPgkbQRwVbfUCEtXVWLxBKdPymQeHVoh5z9mO8=";
|
||||
rev = "68b506d9a9c2c5dde01a078a589520f551d05fe5";
|
||||
hash = "sha256-jNBwkcFb9i5Z6BSMfkTOyrK7HZohAT/yB3cxcCOG54w=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "close-and-restore-tab.yazi";
|
||||
version = "0-unstable-2026-04-22";
|
||||
version = "0-unstable-2025-05-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "MasouShizuka";
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "compress.yazi";
|
||||
version = "25.12.29-unstable-2026-03-15";
|
||||
version = "0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "KKV9";
|
||||
repo = "compress.yazi";
|
||||
rev = "46a6b9f02ff2f8aced466a1f01a3fe241f1cd45f";
|
||||
tag = "0.6";
|
||||
hash = "sha256-Mby185FCJY6nqHcHDQu+D5SLk+wGcyeUHK8yAvrd4TM=";
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "convert.yazi";
|
||||
version = "0-unstable-2026-04-22";
|
||||
version = "0-unstable-2025-06-28";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "atareao";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "diff.yazi";
|
||||
version = "26.1.22-unstable-2026-01-24";
|
||||
version = "0-unstable-2026-01-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "full-border.yazi";
|
||||
version = "25.2.26-unstable-2026-04-22";
|
||||
version = "0-unstable-2026-04-22";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "git.yazi";
|
||||
version = "26.1.22-unstable-2026-02-27";
|
||||
version = "0-unstable-2026-02-27";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "gvfs.yazi";
|
||||
version = "25.5.31-unstable-2026-03-29";
|
||||
version = "0-unstable-2026-03-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boydaihungst";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "jump-to-char.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2025-06-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "lazygit.yazi";
|
||||
version = "0-unstable-2026-03-12";
|
||||
version = "0-unstable-2026-05-02";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Lil-Dank";
|
||||
repo = "lazygit.yazi";
|
||||
rev = "8c4086c813c5856ab9571ae9142ed7d40ed3211e";
|
||||
hash = "sha256-YpRWnR5fEXzHY9yBFNKy1NvTzHa8B1UhS2Qrfe9+Tpg=";
|
||||
rev = "e73fd74c2af3300368b33da1cfbab6a8649a41a8";
|
||||
hash = "sha256-KPvjXjYE0W4Q2xZiVfMwZbtalHt0FbgLtEK4sUWbYOI=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "lsar.yazi";
|
||||
version = "26.1.22-unstable-2026-01-24";
|
||||
version = "0-unstable-2026-01-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "mactag.yazi";
|
||||
version = "26.1.22-unstable-2026-04-10";
|
||||
version = "0-unstable-2026-04-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "mediainfo.yazi";
|
||||
version = "26.1.22-unstable-2026-04-10";
|
||||
version = "0-unstable-2026-04-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boydaihungst";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "mount.yazi";
|
||||
version = "25.12.29-unstable-2026-04-09";
|
||||
version = "0-unstable-2026-04-09";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "office.yazi";
|
||||
version = "0-unstable-2026-04-22";
|
||||
version = "0-unstable-2025-09-20";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "macydnah";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "piper.yazi";
|
||||
version = "26.1.22-unstable-2026-01-24";
|
||||
version = "0-unstable-2026-01-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "relative-motions.yazi";
|
||||
version = "25.5.28-unstable-2025-07-09";
|
||||
version = "0-unstable-2025-07-09";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "dedukun";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "restore.yazi";
|
||||
version = "25.5.31-unstable-2026-04-04";
|
||||
version = "0-unstable-2026-04-04";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boydaihungst";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "smart-enter.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2025-06-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "smart-filter.yazi";
|
||||
version = "25.12.29-unstable-2025-12-29";
|
||||
version = "0-unstable-2025-12-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "smart-paste.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2025-06-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
mkYaziPlugin {
|
||||
pname = "split-tabs.yazi";
|
||||
version = "0-unstable-2026-04-13";
|
||||
version = "0-unstable-2026-05-13";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "terrakok";
|
||||
repo = "split-tabs.yazi";
|
||||
rev = "6c0931840d764bffa0c38677b6a84e69928e283f";
|
||||
hash = "sha256-FqeXVVFk4+aXn8d+LLs8idRBkLLzRPeVol6vMCh6mQ4=";
|
||||
rev = "ca95efc94a3a62e6e58c741f60801c1a0ddba1a6";
|
||||
hash = "sha256-ic09opWZcoJ874bU2HN+5Y9mbnZEnvds+abqRQYuiYE=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "sshfs.yazi";
|
||||
version = "2.0.0-unstable-2026-04-15";
|
||||
version = "2.1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "uhs-robert";
|
||||
repo = "sshfs.yazi";
|
||||
rev = "7ba17a8c8498fca9f0a9c437704e74b56d96ed96";
|
||||
hash = "sha256-TS3/xl8jbbCoF1LzPYvmG9BRqvlzPg4EZRErlL7S2/M=";
|
||||
tag = "v2.1.0";
|
||||
hash = "sha256-02LzKNptzs6o+YPGJRyYCly/Xqzi/5mvVBS+b28nY6U=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "starship.yazi";
|
||||
version = "25.4.8-unstable-2026-03-22";
|
||||
version = "0-unstable-2026-03-22";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Rolv-Apneseth";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "sudo.yazi";
|
||||
version = "0-unstable-2025-11-05";
|
||||
version = "0-unstable-2026-05-07";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "TD-Sky";
|
||||
repo = "sudo.yazi";
|
||||
rev = "86205aa8044f10b02471be1087f3381bbadc967e";
|
||||
hash = "sha256-mpQLij+Sg88RarCC+0u7JfZ2EqcX4gB7jvy8bfBt90w=";
|
||||
rev = "afd61cedbcd13c549c552766755645069561d28c";
|
||||
hash = "sha256-5wa4fdYo7wOXOzdrigWMtADZIL/7alG8Jw7r8iWz9yA=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "toggle-pane.yazi";
|
||||
version = "25.5.31-unstable-2025-06-18";
|
||||
version = "0-unstable-2026-05-07";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
repo = "plugins";
|
||||
rev = "86d28e4fb4f25f36cc501b8cb0badb37a6b14263";
|
||||
hash = "sha256-m/gJTDm0cVkIdcQ1ZJliPqBhNKoCW1FciLkuq7D1mxo=";
|
||||
rev = "4ffa48f33465c22cce48c5d506295a3eb27c1979";
|
||||
hash = "sha256-wr5QL493A175dRjYSyYpMMJax1RKWaZ3jAdFdL3XXTw=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3 python3Packages.requests python3Packages.packaging nix curl git argparse
|
||||
#!nix-shell -i python3 -p python3 python3Packages.requests python3Packages.packaging python3Packages.nixpkgs-plugin-update nix curl git argparse
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from nixpkgs_plugin_update import make_unstable_version, normalize_release_version
|
||||
from packaging import version
|
||||
from packaging.version import InvalidVersion
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpdateCandidate:
|
||||
"""An upstream revision that might be used to update a plugin."""
|
||||
|
||||
rev: str
|
||||
commit: str | None
|
||||
date: str
|
||||
version: str
|
||||
kind: str
|
||||
|
||||
|
||||
def run_command(cmd: str, capture_output: bool = True) -> str:
|
||||
@@ -65,18 +81,42 @@ def get_default_branch(owner: str, repo: str, headers: dict[str, str]) -> str:
|
||||
print("Falling back to 'main' as default branch")
|
||||
return "main"
|
||||
|
||||
def fetch_plugin_content(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> str:
|
||||
"""Fetch the plugin's main.lua content from GitHub"""
|
||||
default_branch = get_default_branch(owner, repo, headers)
|
||||
plugin_path = f"{plugin_pname}/" if owner == "yazi-rs" else ""
|
||||
main_lua_url = f"https://raw.githubusercontent.com/{owner}/{repo}/{default_branch}/{plugin_path}main.lua"
|
||||
|
||||
def github_get(
|
||||
owner: str,
|
||||
repo: str,
|
||||
path: str,
|
||||
headers: dict[str, str],
|
||||
params: dict[str, str | int] | None = None,
|
||||
allow_404: bool = False,
|
||||
) -> dict | list | None:
|
||||
"""Fetch JSON from the GitHub API."""
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/{path}"
|
||||
|
||||
try:
|
||||
response = requests.get(main_lua_url, headers=headers)
|
||||
response = requests.get(api_url, headers=headers, params=params)
|
||||
if allow_404 and response.status_code == 404:
|
||||
return None
|
||||
response.raise_for_status()
|
||||
return response.text
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
raise RuntimeError(f"Error fetching plugin content: {e}")
|
||||
raise RuntimeError(f"Error fetching {api_url}: {e}")
|
||||
|
||||
|
||||
def fetch_plugin_content(
|
||||
owner: str,
|
||||
repo: str,
|
||||
plugin_pname: str,
|
||||
ref: str,
|
||||
headers: dict[str, str],
|
||||
) -> str:
|
||||
"""Fetch the plugin's main.lua content from GitHub"""
|
||||
plugin_path = f"{plugin_pname}/" if owner == "yazi-rs" else ""
|
||||
content_data = github_get(owner, repo, f"contents/{plugin_path}main.lua", headers, {"ref": ref})
|
||||
if not isinstance(content_data, dict) or "content" not in content_data:
|
||||
raise RuntimeError(f"Could not fetch main.lua at {ref}")
|
||||
|
||||
return base64.b64decode(content_data["content"]).decode("utf-8")
|
||||
|
||||
|
||||
def check_version_compatibility(plugin_content: str, plugin_name: str, yazi_version: str) -> str:
|
||||
@@ -95,40 +135,241 @@ def check_version_compatibility(plugin_content: str, plugin_name: str, yazi_vers
|
||||
return required_version
|
||||
|
||||
|
||||
def get_latest_commit(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> tuple[str, str]:
|
||||
"""Get the latest commit hash and date for the plugin"""
|
||||
def candidate_sort_key(candidate: UpdateCandidate) -> tuple[int, version.Version | str]:
|
||||
"""Sort candidates by parsed version when possible, then by text."""
|
||||
try:
|
||||
return (1, version.parse(candidate.version))
|
||||
except InvalidVersion:
|
||||
return (0, candidate.version)
|
||||
|
||||
|
||||
def normalize_candidate(tag: str | None, kind: str) -> UpdateCandidate | None:
|
||||
"""Create an unresolved release/tag candidate from a GitHub tag."""
|
||||
candidate_version = normalize_release_version(tag) if tag else None
|
||||
if candidate_version is None:
|
||||
return None
|
||||
|
||||
return UpdateCandidate(
|
||||
rev=tag,
|
||||
commit=None,
|
||||
date="unknown",
|
||||
version=candidate_version,
|
||||
kind=kind,
|
||||
)
|
||||
|
||||
|
||||
def resolve_candidate(owner: str, repo: str, candidate: UpdateCandidate, headers: dict[str, str]) -> UpdateCandidate:
|
||||
"""Resolve a release/tag candidate to the commit it points at."""
|
||||
if candidate.commit is not None:
|
||||
return candidate
|
||||
|
||||
commit_data = github_get(owner, repo, f"commits/{candidate.rev}", headers)
|
||||
if not isinstance(commit_data, dict):
|
||||
raise RuntimeError(f"Could not resolve {candidate.rev}")
|
||||
|
||||
return UpdateCandidate(
|
||||
rev=candidate.rev,
|
||||
commit=commit_data["sha"],
|
||||
date=commit_data["commit"]["committer"]["date"].split("T")[0],
|
||||
version=candidate.version,
|
||||
kind=candidate.kind,
|
||||
)
|
||||
|
||||
|
||||
def get_commit_candidates(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get recent default branch commit candidates for a plugin."""
|
||||
default_branch = get_default_branch(owner, repo, headers)
|
||||
|
||||
if owner == "yazi-rs":
|
||||
# For official plugins, get commit info for the specific plugin file
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/commits?path={plugin_pname}/main.lua&per_page=1"
|
||||
commits_data = github_get(
|
||||
owner,
|
||||
repo,
|
||||
"commits",
|
||||
headers,
|
||||
{"path": f"{plugin_pname}/main.lua", "per_page": 100},
|
||||
)
|
||||
if not isinstance(commits_data, list) or not commits_data:
|
||||
raise RuntimeError(f"Could not get recent commits for {plugin_pname}")
|
||||
else:
|
||||
# For third-party plugins, get latest commit on default branch
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/commits/{default_branch}"
|
||||
commits_data = github_get(
|
||||
owner,
|
||||
repo,
|
||||
"commits",
|
||||
headers,
|
||||
{"sha": default_branch, "per_page": 100},
|
||||
)
|
||||
if not isinstance(commits_data, list) or not commits_data:
|
||||
raise RuntimeError(f"Could not get recent commits for {owner}/{repo}")
|
||||
|
||||
try:
|
||||
response = requests.get(api_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
commit_data = response.json()
|
||||
except requests.RequestException as e:
|
||||
raise RuntimeError(f"Error fetching commit data: {e}")
|
||||
|
||||
if owner == "yazi-rs":
|
||||
latest_commit = commit_data[0]["sha"]
|
||||
commit_date = commit_data[0]["commit"]["committer"]["date"].split("T")[0]
|
||||
else:
|
||||
latest_commit = commit_data["sha"]
|
||||
candidates = []
|
||||
for commit_data in commits_data:
|
||||
commit = commit_data["sha"]
|
||||
commit_date = commit_data["commit"]["committer"]["date"].split("T")[0]
|
||||
commit_datetime = datetime.strptime(commit_date, "%Y-%m-%d")
|
||||
|
||||
if not latest_commit:
|
||||
raise RuntimeError("Could not get latest commit hash")
|
||||
candidates.append(
|
||||
UpdateCandidate(
|
||||
rev=commit,
|
||||
commit=commit,
|
||||
date=commit_date,
|
||||
version=make_unstable_version(commit_datetime, None),
|
||||
kind="commit",
|
||||
)
|
||||
)
|
||||
|
||||
return latest_commit, commit_date
|
||||
return candidates
|
||||
|
||||
|
||||
def calculate_sri_hash(owner: str, repo: str, latest_commit: str) -> str:
|
||||
def get_release_candidates(owner: str, repo: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get non-prerelease GitHub release candidates without resolving tags."""
|
||||
releases = github_get(owner, repo, "releases", headers, {"per_page": 100})
|
||||
if not isinstance(releases, list):
|
||||
return []
|
||||
|
||||
candidates = []
|
||||
for release in releases:
|
||||
if release.get("draft") or release.get("prerelease"):
|
||||
continue
|
||||
|
||||
candidate = normalize_candidate(release.get("tag_name"), "release")
|
||||
if candidate is not None:
|
||||
candidates.append(candidate)
|
||||
|
||||
candidates.sort(key=candidate_sort_key, reverse=True)
|
||||
return candidates
|
||||
|
||||
|
||||
def get_tag_candidates(owner: str, repo: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get GitHub tag candidates without resolving tags."""
|
||||
tags = github_get(owner, repo, "tags", headers, {"per_page": 100})
|
||||
if not isinstance(tags, list):
|
||||
return []
|
||||
|
||||
candidates = []
|
||||
for tag in tags:
|
||||
candidate = normalize_candidate(tag.get("name"), "tag")
|
||||
if candidate is not None:
|
||||
candidates.append(candidate)
|
||||
|
||||
candidates.sort(key=candidate_sort_key, reverse=True)
|
||||
return candidates
|
||||
|
||||
|
||||
def get_update_candidates(owner: str, repo: str, plugin_pname: str, headers: dict[str, str]) -> list[UpdateCandidate]:
|
||||
"""Get update candidates, preferring releases, then tags, then commits."""
|
||||
release_candidates = get_release_candidates(owner, repo, headers)
|
||||
if release_candidates:
|
||||
return release_candidates
|
||||
|
||||
tag_candidates = get_tag_candidates(owner, repo, headers)
|
||||
if tag_candidates:
|
||||
return tag_candidates
|
||||
|
||||
return get_commit_candidates(owner, repo, plugin_pname, headers)
|
||||
|
||||
|
||||
def compare_to_current(
|
||||
owner: str,
|
||||
repo: str,
|
||||
old_commit: str,
|
||||
candidate: UpdateCandidate,
|
||||
headers: dict[str, str],
|
||||
) -> str:
|
||||
"""Compare a candidate to the packaged commit."""
|
||||
if old_commit == "unknown":
|
||||
print("Current commit is unknown, skipping to avoid a possible regression")
|
||||
return "unknown"
|
||||
|
||||
if candidate.commit is None:
|
||||
raise RuntimeError(f"Candidate {candidate.rev} is unresolved")
|
||||
|
||||
if old_commit == candidate.commit or old_commit == candidate.rev:
|
||||
return "identical"
|
||||
|
||||
compare_data = github_get(owner, repo, f"compare/{old_commit}...{candidate.commit}", headers, allow_404=True)
|
||||
if not isinstance(compare_data, dict):
|
||||
print(f"Could not compare {old_commit}...{candidate.commit}, skipping to avoid a possible regression")
|
||||
return "unknown"
|
||||
|
||||
return str(compare_data.get("status"))
|
||||
|
||||
|
||||
def is_yazi_compatible(
|
||||
owner: str,
|
||||
repo: str,
|
||||
plugin_name: str,
|
||||
plugin_pname: str,
|
||||
candidate: UpdateCandidate,
|
||||
yazi_version: str,
|
||||
headers: dict[str, str],
|
||||
) -> bool:
|
||||
"""Check if a candidate supports nixpkgs' Yazi version."""
|
||||
try:
|
||||
plugin_content = fetch_plugin_content(owner, repo, plugin_pname, candidate.rev, headers)
|
||||
check_version_compatibility(plugin_content, plugin_name, yazi_version)
|
||||
return True
|
||||
except RuntimeError as e:
|
||||
print(f"Skipping {candidate.rev}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def select_compatible_candidate(
|
||||
owner: str,
|
||||
repo: str,
|
||||
plugin_name: str,
|
||||
plugin_pname: str,
|
||||
old_ref_attr: str,
|
||||
old_ref: str,
|
||||
old_commit: str,
|
||||
old_version: str,
|
||||
yazi_version: str,
|
||||
headers: dict[str, str],
|
||||
) -> UpdateCandidate | None:
|
||||
"""Select the newest compatible candidate that moves the package forward."""
|
||||
candidates = get_update_candidates(owner, repo, plugin_pname, headers)
|
||||
|
||||
for unresolved_candidate in candidates:
|
||||
try:
|
||||
candidate = resolve_candidate(owner, repo, unresolved_candidate, headers)
|
||||
except RuntimeError as e:
|
||||
print(f"Skipping {unresolved_candidate.rev}: {e}")
|
||||
if unresolved_candidate.kind in ("release", "tag"):
|
||||
break
|
||||
continue
|
||||
|
||||
print(f"Checking {plugin_name} {candidate.kind} {candidate.rev} ({candidate.date})")
|
||||
|
||||
compare_status = compare_to_current(owner, repo, old_commit, candidate, headers)
|
||||
if compare_status == "identical":
|
||||
candidate_ref_attr = "rev" if candidate.kind == "commit" else "tag"
|
||||
source_ref_changed = old_ref_attr != candidate_ref_attr or old_ref != candidate.rev
|
||||
if old_version != candidate.version or source_ref_changed:
|
||||
if not is_yazi_compatible(owner, repo, plugin_name, plugin_pname, candidate, yazi_version, headers):
|
||||
break
|
||||
|
||||
return candidate
|
||||
|
||||
print(f"{plugin_name} is already at {candidate.rev}; older candidates will not be used")
|
||||
break
|
||||
|
||||
if compare_status != "ahead":
|
||||
print(f"Skipping {candidate.rev}: compare status is {compare_status}, not ahead")
|
||||
if candidate.kind in ("release", "tag"):
|
||||
print(f"{candidate.rev} is not newer than the packaged revision; older {candidate.kind}s will not be used")
|
||||
break
|
||||
continue
|
||||
|
||||
if not is_yazi_compatible(owner, repo, plugin_name, plugin_pname, candidate, yazi_version, headers):
|
||||
continue
|
||||
|
||||
return candidate
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def calculate_sri_hash(owner: str, repo: str, rev: str) -> str:
|
||||
"""Calculate the SRI hash for the plugin source"""
|
||||
prefetch_url = f"https://github.com/{owner}/{repo}/archive/{latest_commit}.tar.gz"
|
||||
prefetch_url = f"https://github.com/{owner}/{repo}/archive/{rev}.tar.gz"
|
||||
|
||||
try:
|
||||
new_hash = run_command(f"nix-prefetch-url --unpack --type sha256 {prefetch_url} 2>/dev/null")
|
||||
@@ -167,16 +408,39 @@ def write_nix_file(file_path: str, content: str) -> None:
|
||||
raise RuntimeError(f"Error writing to file {file_path}: {e}")
|
||||
|
||||
|
||||
def update_nix_file(default_nix_path: str, latest_commit: str, new_version: str, new_hash: str) -> None:
|
||||
def get_source_ref(nix_content: str) -> tuple[str, str]:
|
||||
"""Get the source ref attribute from a Nix file."""
|
||||
source_ref_match = re.search(r'\b(rev|tag) = "([^"]*)"', nix_content)
|
||||
if source_ref_match is None:
|
||||
raise RuntimeError("Could not find rev or tag attribute")
|
||||
|
||||
return source_ref_match.group(1), source_ref_match.group(2)
|
||||
|
||||
|
||||
def resolve_ref_commit(owner: str, repo: str, ref: str, headers: dict[str, str]) -> str:
|
||||
"""Resolve a GitHub ref to its commit."""
|
||||
commit_data = github_get(owner, repo, f"commits/{ref}", headers)
|
||||
if not isinstance(commit_data, dict):
|
||||
raise RuntimeError(f"Could not resolve {ref}")
|
||||
|
||||
return commit_data["sha"]
|
||||
|
||||
|
||||
def update_nix_file(default_nix_path: str, candidate: UpdateCandidate, new_hash: str) -> None:
|
||||
"""Update the default.nix file with new version, revision and hash"""
|
||||
default_nix_content = read_nix_file(default_nix_path)
|
||||
|
||||
default_nix_content = re.sub(r'rev = "[^"]*"', f'rev = "{latest_commit}"', default_nix_content)
|
||||
source_ref_attr = "rev" if candidate.kind == "commit" else "tag"
|
||||
default_nix_content = re.sub(
|
||||
r'\b(rev|tag) = "[^"]*"',
|
||||
f'{source_ref_attr} = "{candidate.rev}"',
|
||||
default_nix_content,
|
||||
)
|
||||
|
||||
if 'version = "' in default_nix_content:
|
||||
default_nix_content = re.sub(r'version = "[^"]*"', f'version = "{new_version}"', default_nix_content)
|
||||
default_nix_content = re.sub(r'version = "[^"]*"', f'version = "{candidate.version}"', default_nix_content)
|
||||
else:
|
||||
default_nix_content = re.sub(r'(pname = "[^"]*";)', f'\\1\n version = "{new_version}";', default_nix_content)
|
||||
default_nix_content = re.sub(r'(pname = "[^"]*";)', f'\\1\n version = "{candidate.version}";', default_nix_content)
|
||||
|
||||
if 'hash = "' in default_nix_content:
|
||||
default_nix_content = re.sub(r'hash = "[^"]*"', f'hash = "{new_hash}"', default_nix_content)
|
||||
@@ -202,6 +466,11 @@ def get_all_plugins(nixpkgs_dir: str) -> list[dict[str, str]]:
|
||||
|
||||
excluded_attrs = ["mkYaziPlugin", "override", "overrideDerivation", "overrideAttrs", "recurseForDerivations"]
|
||||
plugin_names = [name for name in plugin_names if name not in excluded_attrs]
|
||||
plugin_names = [
|
||||
name
|
||||
for name in plugin_names
|
||||
if Path(nixpkgs_dir, "pkgs/by-name/ya/yazi/plugins", name, "default.nix").exists()
|
||||
]
|
||||
|
||||
plugins = []
|
||||
for name in plugin_names:
|
||||
@@ -247,8 +516,7 @@ def update_single_plugin(nixpkgs_dir: str, plugin_name: str, plugin_pname: str)
|
||||
nix_content = read_nix_file(default_nix_path)
|
||||
old_version_match = re.search(r'version = "([^"]*)"', nix_content)
|
||||
old_version = old_version_match.group(1) if old_version_match else "unknown"
|
||||
old_commit_match = re.search(r'rev = "([^"]*)"', nix_content)
|
||||
old_commit = old_commit_match.group(1) if old_commit_match else "unknown"
|
||||
old_ref_attr, old_ref = get_source_ref(nix_content)
|
||||
|
||||
plugin_info = get_plugin_info(nixpkgs_dir, plugin_name)
|
||||
owner = plugin_info["owner"]
|
||||
@@ -257,34 +525,43 @@ def update_single_plugin(nixpkgs_dir: str, plugin_name: str, plugin_pname: str)
|
||||
yazi_version = get_yazi_version(nixpkgs_dir)
|
||||
|
||||
headers = get_github_headers()
|
||||
try:
|
||||
old_commit = old_ref if old_ref_attr == "rev" else resolve_ref_commit(owner, repo, old_ref, headers)
|
||||
except RuntimeError as e:
|
||||
print(f"Could not resolve current {old_ref_attr} {old_ref}: {e}")
|
||||
old_commit = "unknown"
|
||||
|
||||
plugin_content = fetch_plugin_content(owner, repo, plugin_pname, headers)
|
||||
required_version = check_version_compatibility(plugin_content, plugin_name, yazi_version)
|
||||
|
||||
latest_commit, commit_date = get_latest_commit(owner, repo, plugin_pname, headers)
|
||||
print(f"Checking {plugin_name} latest commit {latest_commit} ({commit_date})")
|
||||
|
||||
if latest_commit == old_commit:
|
||||
print(f"No changes for {plugin_name}, already at latest commit {latest_commit}")
|
||||
candidate = select_compatible_candidate(
|
||||
owner,
|
||||
repo,
|
||||
plugin_name,
|
||||
plugin_pname,
|
||||
old_ref_attr,
|
||||
old_ref,
|
||||
old_commit,
|
||||
old_version,
|
||||
yazi_version,
|
||||
headers,
|
||||
)
|
||||
if candidate is None:
|
||||
print(f"No forward compatible update found for {plugin_name}")
|
||||
return None
|
||||
|
||||
print(f"Updating {plugin_name} from commit {old_commit} to {latest_commit}")
|
||||
print(f"Updating {plugin_name} from {old_commit} to {candidate.rev}")
|
||||
|
||||
new_version = f"{required_version}-unstable-{commit_date}"
|
||||
|
||||
new_hash = calculate_sri_hash(owner, repo, latest_commit)
|
||||
new_hash = calculate_sri_hash(owner, repo, candidate.rev)
|
||||
print(f"Generated SRI hash: {new_hash}")
|
||||
|
||||
update_nix_file(default_nix_path, latest_commit, new_version, new_hash)
|
||||
update_nix_file(default_nix_path, candidate, new_hash)
|
||||
|
||||
print(f"Successfully updated {plugin_name} from {old_version} to {new_version}")
|
||||
print(f"Successfully updated {plugin_name} from {old_version} to {candidate.version}")
|
||||
|
||||
return {
|
||||
"name": plugin_name,
|
||||
"old_version": old_version,
|
||||
"new_version": new_version,
|
||||
"new_version": candidate.version,
|
||||
"old_commit": old_commit,
|
||||
"new_commit": latest_commit,
|
||||
"new_commit": candidate.commit,
|
||||
"owner": owner,
|
||||
"repo": repo,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "vcs-files.yazi";
|
||||
version = "26.1.22-unstable-2026-04-10";
|
||||
version = "0-unstable-2026-04-10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "yazi-rs";
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "yafg.yazi";
|
||||
version = "0-unstable-2026-01-10";
|
||||
version = "0-unstable-2026-05-06";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "XYenon";
|
||||
repo = "yafg.yazi";
|
||||
rev = "dd03b133d6cd1ff92368360558da193517169f9e";
|
||||
hash = "sha256-xTZ+6KRr85A4QpPWAE9QN1AnUVnCw/tvRvsWOmmayao=";
|
||||
rev = "e6ba85125bfa4e3a60ef28b70949299712103b2a";
|
||||
hash = "sha256-IKQscTTirtfbsXKzCmaokPDrQZqXa4MSY2+6DbEQluU=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
}:
|
||||
mkYaziPlugin {
|
||||
pname = "yatline.yazi";
|
||||
version = "25.12.29-unstable-2026-01-27";
|
||||
version = "0.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "imsi32";
|
||||
repo = "yatline.yazi";
|
||||
rev = "c5d4b487d6277dd68ea9d3c6537641bf4ae9cf8e";
|
||||
tag = "v0.5.0";
|
||||
hash = "sha256-HjTRAfUHs6vlEWKruQWeA2wT/Mcd+WEHM90egFTYcWQ=";
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user