yaziPlugins: rewrite update script in python
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
}:
|
||||
let
|
||||
root = ./.;
|
||||
updateScript = ./update.sh;
|
||||
updateScript = ./update.py;
|
||||
|
||||
mkYaziPlugin =
|
||||
args@{
|
||||
|
||||
Executable
+256
@@ -0,0 +1,256 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3 python3Packages.requests python3Packages.packaging nix curl git
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, Tuple
|
||||
|
||||
import requests
|
||||
from packaging import version
|
||||
|
||||
|
||||
def run_command(cmd: str, capture_output: bool = True) -> str:
|
||||
"""Run a shell command and return its output"""
|
||||
result = subprocess.run(cmd, shell=True, text=True, capture_output=capture_output)
|
||||
if result.returncode != 0:
|
||||
if capture_output:
|
||||
print(f"Error running command: {cmd}")
|
||||
print(f"stderr: {result.stderr}")
|
||||
sys.exit(1)
|
||||
return result.stdout.strip() if capture_output else ""
|
||||
|
||||
|
||||
def get_plugin_info(nixpkgs_dir: str, plugin_name: str) -> Dict[str, str]:
|
||||
"""Get plugin repository information from Nix"""
|
||||
owner = run_command(f"nix eval --raw -f {nixpkgs_dir} yaziPlugins.\"{plugin_name}\".src.owner")
|
||||
repo = run_command(f"nix eval --raw -f {nixpkgs_dir} yaziPlugins.\"{plugin_name}\".src.repo")
|
||||
|
||||
return {
|
||||
"owner": owner,
|
||||
"repo": repo
|
||||
}
|
||||
|
||||
|
||||
def get_yazi_version(nixpkgs_dir: str) -> str:
|
||||
"""Get the current Yazi version from Nix"""
|
||||
return run_command(f"nix eval --raw -f {nixpkgs_dir} yazi-unwrapped.version")
|
||||
|
||||
|
||||
|
||||
def get_github_headers() -> Dict[str, str]:
|
||||
"""Create headers for GitHub API requests"""
|
||||
headers = {"Accept": "application/vnd.github.v3+json"}
|
||||
github_token = os.environ.get("GITHUB_TOKEN")
|
||||
if github_token:
|
||||
headers["Authorization"] = f"token {github_token}"
|
||||
return headers
|
||||
|
||||
|
||||
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"""
|
||||
plugin_path = f"{plugin_pname}/" if owner == "yazi-rs" else ""
|
||||
main_lua_url = f"https://raw.githubusercontent.com/{owner}/{repo}/main/{plugin_path}main.lua"
|
||||
|
||||
try:
|
||||
response = requests.get(main_lua_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.text
|
||||
except requests.RequestException as e:
|
||||
print(f"Error fetching plugin content: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def check_version_compatibility(plugin_content: str, plugin_name: str, yazi_version: str) -> str:
|
||||
"""Check if the plugin is compatible with the current Yazi version"""
|
||||
required_version_match = re.search(r"since ([0-9.]+)", plugin_content.split("\n")[0])
|
||||
required_version = required_version_match.group(1) if required_version_match else "0"
|
||||
|
||||
if required_version == "0":
|
||||
print(f"No version requirement found for {plugin_name}, assuming compatible with any Yazi version")
|
||||
else:
|
||||
# Check if the plugin is compatible with current Yazi version
|
||||
if version.parse(required_version) > version.parse(yazi_version):
|
||||
print(f"{plugin_name} plugin requires Yazi {required_version}, but we have {yazi_version}")
|
||||
sys.exit(0)
|
||||
|
||||
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"""
|
||||
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"
|
||||
else:
|
||||
# For third-party plugins, get latest commit on main branch
|
||||
api_url = f"https://api.github.com/repos/{owner}/{repo}/commits/main"
|
||||
|
||||
try:
|
||||
response = requests.get(api_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
commit_data = response.json()
|
||||
except requests.RequestException as e:
|
||||
print(f"Error fetching commit data: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
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"]
|
||||
commit_date = commit_data["commit"]["committer"]["date"].split("T")[0]
|
||||
|
||||
if not latest_commit:
|
||||
print("Error: Could not get latest commit hash")
|
||||
sys.exit(1)
|
||||
|
||||
return latest_commit, commit_date
|
||||
|
||||
|
||||
def calculate_sri_hash(owner: str, repo: str, latest_commit: str) -> str:
|
||||
"""Calculate the SRI hash for the plugin source"""
|
||||
prefetch_url = f"https://github.com/{owner}/{repo}/archive/{latest_commit}.tar.gz"
|
||||
|
||||
try:
|
||||
new_hash = run_command(f"nix-prefetch-url --unpack --type sha256 {prefetch_url} 2>/dev/null")
|
||||
|
||||
# If the hash is not in SRI format, convert it
|
||||
if not new_hash.startswith("sha256-"):
|
||||
# Try to convert the hash to SRI format
|
||||
new_hash = run_command(f"nix hash to-sri --type sha256 {new_hash} 2>/dev/null")
|
||||
|
||||
# If that fails, try another approach
|
||||
if not new_hash.startswith("sha256-"):
|
||||
print("Warning: Failed to get SRI hash directly, trying alternative method...")
|
||||
raw_hash = run_command(f"nix-prefetch-url --type sha256 {prefetch_url} 2>/dev/null")
|
||||
new_hash = run_command(f"nix hash to-sri --type sha256 {raw_hash} 2>/dev/null")
|
||||
except Exception as e:
|
||||
print(f"Error calculating hash: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Verify we got a valid SRI hash
|
||||
if not new_hash.startswith("sha256-"):
|
||||
print(f"Error: Failed to generate valid SRI hash. Output was: {new_hash}")
|
||||
sys.exit(1)
|
||||
|
||||
return new_hash
|
||||
|
||||
|
||||
def read_nix_file(file_path: str) -> str:
|
||||
"""Read the content of a Nix file"""
|
||||
try:
|
||||
with open(file_path, 'r') as f:
|
||||
return f.read()
|
||||
except IOError as e:
|
||||
print(f"Error reading file {file_path}: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def write_nix_file(file_path: str, content: str) -> None:
|
||||
"""Write content to a Nix file"""
|
||||
try:
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(content)
|
||||
except IOError as e:
|
||||
print(f"Error writing to file {file_path}: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def update_nix_file(default_nix_path: str, latest_commit: str, new_version: str, new_hash: str) -> None:
|
||||
"""Update the default.nix file with new version, revision and hash"""
|
||||
default_nix_content = read_nix_file(default_nix_path)
|
||||
|
||||
# Update the revision in default.nix
|
||||
default_nix_content = re.sub(r'rev = "[^"]*"', f'rev = "{latest_commit}"', default_nix_content)
|
||||
|
||||
# Update the version in default.nix
|
||||
if 'version = "' in default_nix_content:
|
||||
default_nix_content = re.sub(r'version = "[^"]*"', f'version = "{new_version}"', default_nix_content)
|
||||
else:
|
||||
# Add version attribute after pname if it doesn't exist
|
||||
default_nix_content = re.sub(r'(pname = "[^"]*";)', f'\\1\n version = "{new_version}";', default_nix_content)
|
||||
|
||||
# Update hash in default.nix
|
||||
if 'hash = "' in default_nix_content:
|
||||
default_nix_content = re.sub(r'hash = "[^"]*"', f'hash = "{new_hash}"', default_nix_content)
|
||||
elif 'fetchFromGitHub' in default_nix_content:
|
||||
default_nix_content = re.sub(r'sha256 = "[^"]*"', f'sha256 = "{new_hash}"', default_nix_content)
|
||||
else:
|
||||
print(f"Error: Could not find hash attribute in {default_nix_path}")
|
||||
sys.exit(1)
|
||||
|
||||
# Write the updated content back to the file
|
||||
write_nix_file(default_nix_path, default_nix_content)
|
||||
|
||||
# Verify the hash was updated
|
||||
updated_content = read_nix_file(default_nix_path)
|
||||
if f'hash = "{new_hash}"' in updated_content or f'sha256 = "{new_hash}"' in updated_content:
|
||||
print(f"Successfully updated hash to: {new_hash}")
|
||||
else:
|
||||
print(f"Error: Failed to update hash in {default_nix_path}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def validate_environment() -> Tuple[str, str, str]:
|
||||
"""Validate environment variables and paths"""
|
||||
nixpkgs_dir = os.getcwd()
|
||||
|
||||
plugin_name = os.environ.get("PLUGIN_NAME")
|
||||
plugin_pname = os.environ.get("PLUGIN_PNAME")
|
||||
|
||||
if not plugin_name or not plugin_pname:
|
||||
print("Error: PLUGIN_NAME and PLUGIN_PNAME environment variables must be set")
|
||||
sys.exit(1)
|
||||
|
||||
plugin_dir = f"{nixpkgs_dir}/pkgs/by-name/ya/yazi/plugins/{plugin_name}"
|
||||
if not Path(f"{plugin_dir}/default.nix").exists():
|
||||
print(f"Error: Could not find default.nix for plugin {plugin_name} at {plugin_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
return nixpkgs_dir, plugin_name, plugin_pname
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to update a Yazi plugin"""
|
||||
# Basic setup and validation
|
||||
nixpkgs_dir, plugin_name, plugin_pname = validate_environment()
|
||||
plugin_dir = f"{nixpkgs_dir}/pkgs/by-name/ya/yazi/plugins/{plugin_name}"
|
||||
default_nix_path = f"{plugin_dir}/default.nix"
|
||||
|
||||
# Get repository info
|
||||
plugin_info = get_plugin_info(nixpkgs_dir, plugin_name)
|
||||
owner = plugin_info["owner"]
|
||||
repo = plugin_info["repo"]
|
||||
|
||||
# Get Yazi version separately
|
||||
yazi_version = get_yazi_version(nixpkgs_dir)
|
||||
|
||||
# Setup GitHub API headers
|
||||
headers = get_github_headers()
|
||||
|
||||
# Check plugin compatibility with current Yazi version
|
||||
plugin_content = fetch_plugin_content(owner, repo, plugin_pname, headers)
|
||||
required_version = check_version_compatibility(plugin_content, plugin_name, yazi_version)
|
||||
|
||||
# Get latest commit info
|
||||
latest_commit, commit_date = get_latest_commit(owner, repo, plugin_pname, headers)
|
||||
print(f"Updating {plugin_name} to commit {latest_commit} ({commit_date})")
|
||||
|
||||
# Generate new version string
|
||||
new_version = f"{required_version}-unstable-{commit_date}"
|
||||
|
||||
# Calculate hash for the plugin
|
||||
new_hash = calculate_sri_hash(owner, repo, latest_commit)
|
||||
print(f"Generated SRI hash: {new_hash}")
|
||||
|
||||
# Update the default.nix file
|
||||
update_nix_file(default_nix_path, latest_commit, new_version, new_hash)
|
||||
|
||||
print(f"Successfully updated {plugin_name} to version {new_version} (commit {latest_commit})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p bash curl coreutils jq git
|
||||
|
||||
set -e
|
||||
|
||||
# Basic setup and validation
|
||||
NIXPKGS_DIR="$PWD"
|
||||
|
||||
if [ "${PLUGIN_NAME:-}" = "" ] || [ "${PLUGIN_PNAME:-}" = "" ]; then
|
||||
echo "Error: PLUGIN_NAME and PLUGIN_PNAME environment variables must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PLUGIN_DIR="$NIXPKGS_DIR/pkgs/by-name/ya/yazi/plugins/$PLUGIN_NAME"
|
||||
if [ ! -f "$PLUGIN_DIR/default.nix" ]; then
|
||||
echo "Error: Could not find default.nix for plugin $PLUGIN_NAME at $PLUGIN_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GITHUB_HEADER=(-H "Accept: application/vnd.github.v3+json")
|
||||
if [ "${GITHUB_TOKEN:-}" != "" ]; then
|
||||
GITHUB_HEADER+=(-H "Authorization: token $GITHUB_TOKEN")
|
||||
fi
|
||||
|
||||
# Get repository info and Yazi version
|
||||
OWNER=$(nix eval --raw -f "$NIXPKGS_DIR" yaziPlugins."$PLUGIN_NAME".src.owner)
|
||||
REPO=$(nix eval --raw -f "$NIXPKGS_DIR" yaziPlugins."$PLUGIN_NAME".src.repo)
|
||||
YAZI_VERSION=$(nix eval --raw -f "$NIXPKGS_DIR" yazi-unwrapped.version)
|
||||
|
||||
# Check plugin compatibility with current Yazi version
|
||||
PLUGIN_PATH="$([[ $OWNER == "yazi-rs" ]] && echo "$PLUGIN_PNAME/" || echo "")"
|
||||
MAIN_LUA_URL="https://raw.githubusercontent.com/$OWNER/$REPO/main/${PLUGIN_PATH}main.lua"
|
||||
PLUGIN_CONTENT=$(curl --silent "${GITHUB_HEADER[@]}" "$MAIN_LUA_URL")
|
||||
REQUIRED_VERSION=$(echo "$PLUGIN_CONTENT" | head -n 1 | grep -o "since [0-9.]*" | sed 's/since \([0-9.]*\)/\1/')
|
||||
|
||||
# If no version requirement is found, default to "0"
|
||||
if [ "$REQUIRED_VERSION" = "" ]; then
|
||||
echo "No version requirement found for $PLUGIN_NAME, assuming compatible with any Yazi version"
|
||||
REQUIRED_VERSION="0"
|
||||
else
|
||||
# Check if the plugin is compatible with current Yazi version
|
||||
if ! printf "%s\n%s\n" "$REQUIRED_VERSION" "$YAZI_VERSION" | sort -C -V; then
|
||||
echo "$PLUGIN_NAME plugin requires Yazi $REQUIRED_VERSION, but we have $YAZI_VERSION"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get latest commit info
|
||||
if [ "$OWNER" == "yazi-rs" ]; then
|
||||
# For official plugins, get commit info for the specific plugin file
|
||||
API_URL="https://api.github.com/repos/$OWNER/$REPO/commits?path=$PLUGIN_PNAME/main.lua&per_page=1"
|
||||
else
|
||||
# For third-party plugins, get latest commit on main branch
|
||||
API_URL="https://api.github.com/repos/$OWNER/$REPO/commits/main"
|
||||
fi
|
||||
|
||||
if [ "$OWNER" == "yazi-rs" ]; then
|
||||
COMMIT_DATA=$(curl --silent "${GITHUB_HEADER[@]}" "$API_URL")
|
||||
LATEST_COMMIT=$(echo "$COMMIT_DATA" | jq -r '.[0].sha')
|
||||
COMMIT_DATE=$(echo "$COMMIT_DATA" | jq -r '.[0].commit.committer.date' | cut -d'T' -f1)
|
||||
else
|
||||
COMMIT_DATA=$(curl --silent "${GITHUB_HEADER[@]}" "$API_URL")
|
||||
LATEST_COMMIT=$(echo "$COMMIT_DATA" | jq -r '.sha')
|
||||
COMMIT_DATE=$(echo "$COMMIT_DATA" | jq -r '.commit.committer.date' | cut -d'T' -f1)
|
||||
fi
|
||||
|
||||
if [ "$LATEST_COMMIT" = "" ] || [ "$LATEST_COMMIT" == "null" ]; then
|
||||
echo "Error: Could not get latest commit hash for $PLUGIN_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating $PLUGIN_NAME to commit $LATEST_COMMIT ($COMMIT_DATE)"
|
||||
|
||||
# Update version and revision
|
||||
NEW_VERSION="${REQUIRED_VERSION}-unstable-${COMMIT_DATE}"
|
||||
|
||||
# Update the revision in default.nix
|
||||
sed -i "s/rev = \"[^\"]*\"/rev = \"$LATEST_COMMIT\"/" "$PLUGIN_DIR/default.nix"
|
||||
|
||||
# Update the version in default.nix
|
||||
if grep -q 'version = "' "$PLUGIN_DIR/default.nix"; then
|
||||
sed -i "s/version = \"[^\"]*\"/version = \"$NEW_VERSION\"/" "$PLUGIN_DIR/default.nix"
|
||||
else
|
||||
# Add version attribute after pname if it doesn't exist
|
||||
sed -i "/pname = \"[^\"]*\"/a \ \ version = \"$NEW_VERSION\";" "$PLUGIN_DIR/default.nix"
|
||||
fi
|
||||
|
||||
# Update the hash
|
||||
# Calculate hash directly for all plugins
|
||||
PREFETCH_URL="https://github.com/$OWNER/$REPO/archive/$LATEST_COMMIT.tar.gz"
|
||||
|
||||
# Get the hash directly in SRI format
|
||||
NEW_HASH=$(nix-prefetch-url --unpack --type sha256 "$PREFETCH_URL" 2>/dev/null)
|
||||
|
||||
# If the hash is not in SRI format, convert it
|
||||
if [[ ! "$NEW_HASH" =~ ^sha256- ]]; then
|
||||
# Try to convert the hash to SRI format
|
||||
NEW_HASH=$(nix hash to-sri --type sha256 "$NEW_HASH" 2>/dev/null)
|
||||
|
||||
# If that fails, try another approach
|
||||
if [[ ! "$NEW_HASH" =~ ^sha256- ]]; then
|
||||
echo "Warning: Failed to get SRI hash directly, trying alternative method..."
|
||||
RAW_HASH=$(nix-prefetch-url --type sha256 "$PREFETCH_URL" 2>/dev/null)
|
||||
NEW_HASH=$(nix hash to-sri --type sha256 "$RAW_HASH" 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify we got a valid SRI hash (starts with sha256-)
|
||||
if [[ ! "$NEW_HASH" =~ ^sha256- ]]; then
|
||||
echo "Error: Failed to generate valid SRI hash. Output was:"
|
||||
echo "$NEW_HASH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Generated SRI hash: $NEW_HASH"
|
||||
|
||||
# Update hash in default.nix
|
||||
if grep -q 'hash = "' "$PLUGIN_DIR/default.nix"; then
|
||||
sed -i "s|hash = \"[^\"]*\"|hash = \"$NEW_HASH\"|" "$PLUGIN_DIR/default.nix"
|
||||
else
|
||||
# For files that use fetchFromGitHub, update the hash there
|
||||
if grep -q 'fetchFromGitHub' "$PLUGIN_DIR/default.nix"; then
|
||||
sed -i "s|sha256 = \"[^\"]*\"|sha256 = \"$NEW_HASH\"|" "$PLUGIN_DIR/default.nix"
|
||||
else
|
||||
echo "Error: Could not find hash attribute in $PLUGIN_DIR/default.nix"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify the hash was updated
|
||||
if grep -q "hash = \"$NEW_HASH\"" "$PLUGIN_DIR/default.nix" || grep -q "sha256 = \"$NEW_HASH\"" "$PLUGIN_DIR/default.nix"; then
|
||||
echo "Successfully updated hash to: $NEW_HASH"
|
||||
else
|
||||
echo "Error: Failed to update hash in $PLUGIN_DIR/default.nix"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update the revision in default.nix
|
||||
sed -i "s/rev = \"[^\"]*\"/rev = \"$LATEST_COMMIT\"/" "$PLUGIN_DIR/default.nix"
|
||||
|
||||
echo "Successfully updated $PLUGIN_NAME to version $NEW_VERSION (commit $LATEST_COMMIT)"
|
||||
Reference in New Issue
Block a user