Files
FastAnime/viu_media/cli/utils/update.py
2025-08-18 02:14:56 +03:00

176 lines
5.3 KiB
Python

import os
import pathlib
import re
import shlex
import shutil
import subprocess
import sys
from httpx import get
from rich import print
from rich.console import Console
from rich.markdown import Markdown
from ...core.constants import (
AUTHOR,
CLI_NAME_LOWER,
GIT_REPO,
PROJECT_NAME,
__version__,
)
API_URL = f"https://api.{GIT_REPO}/repos/{AUTHOR}/{CLI_NAME_LOWER}/releases/latest"
def print_release_json(release_json):
version = release_json.get("tag_name", "unknown")
release_name = release_json.get("name", version)
release_body = release_json.get("body", "No release notes available.")
published_at = release_json.get("published_at", "unknown")
console = Console()
print(f"[bold cyan]Release: {release_name}[/]")
print(f"[dim]Version: {version}[/]")
print(f"[dim]Published: {published_at}[/]")
print()
# Display release notes as markdown if available
if release_body and release_body.strip():
markdown = Markdown(release_body)
console.print(markdown)
def check_for_updates():
USER_AGENT = f"{CLI_NAME_LOWER} user"
try:
response = get(
API_URL,
headers={
"User-Agent": USER_AGENT,
"X-GitHub-Api-Version": "2022-11-28",
"Accept": "application/vnd.github+json",
},
)
except Exception:
print("You are not connected to the internet")
return True, {}
if response.status_code == 200:
release_json = response.json()
remote_tag = list(
map(int, release_json["tag_name"].replace("v", "").split("."))
)
local_tag = list(map(int, __version__.replace("v", "").split(".")))
if (
(remote_tag[0] > local_tag[0])
or (remote_tag[1] > local_tag[1] and remote_tag[0] == local_tag[0])
or (
remote_tag[2] > local_tag[2]
and remote_tag[0] == local_tag[0]
and remote_tag[1] == local_tag[1]
)
):
is_latest = False
else:
is_latest = True
return (is_latest, release_json)
else:
print("Failed to check for updates")
print(response.text)
return (True, {})
def is_git_repo(author, repository):
# Check if the current directory contains a .git folder
git_dir = pathlib.Path(".git")
if not git_dir.exists() or not git_dir.is_dir():
return False
# Check if the config file exists
config_path = git_dir / "config"
if not config_path.exists():
return False
try:
# Read the .git/config file to find the remote repository URL
with config_path.open("r") as git_config:
git_config_content = git_config.read()
except (FileNotFoundError, PermissionError):
return False
# Use regex to find the repository URL in the config file
repo_name_pattern = r"url\s*=\s*.+/([^/]+/[^/]+)\.git"
match = re.search(repo_name_pattern, git_config_content)
# Return True if match found and repository name matches
return bool(match) and match.group(1) == f"{author}/{repository}"
def update_app(force=False):
is_latest, release_json = check_for_updates()
if is_latest and not force:
print("[green]App is up to date[/]")
return False, release_json
tag_name = release_json["tag_name"]
print("[cyan]Updating app to version %s[/]" % tag_name)
if os.path.exists("/nix/store") and os.path.exists("/run/current-system"):
NIX = shutil.which("nix")
if not NIX:
print("[red]Cannot find nix, it looks like your system is broken.[/]")
return False, release_json
process = subprocess.run(
[NIX, "profile", "upgrade", CLI_NAME_LOWER], check=False
)
elif is_git_repo(AUTHOR, CLI_NAME_LOWER):
GIT_EXECUTABLE = shutil.which("git")
args = [
GIT_EXECUTABLE,
"pull",
]
print(f"Pulling latest changes from the repository via git: {shlex.join(args)}")
if not GIT_EXECUTABLE:
print("[red]Cannot find git please install it.[/]")
return False, release_json
process = subprocess.run(
args,
check=False,
)
elif UV := shutil.which("uv"):
process = subprocess.run([UV, "tool", "upgrade", PROJECT_NAME], check=False)
elif PIPX := shutil.which("pipx"):
process = subprocess.run([PIPX, "upgrade", PROJECT_NAME], check=False)
else:
PYTHON_EXECUTABLE = sys.executable
args = [
PYTHON_EXECUTABLE,
"-m",
"pip",
"install",
PROJECT_NAME,
"-U",
"--no-warn-script-location",
]
if sys.prefix == sys.base_prefix:
# ensure NOT in a venv, where --user flag can cause an error.
# TODO: Get value of 'include-system-site-packages' in pyenv.cfg.
args.append("--user")
process = subprocess.run(args, check=False)
if process.returncode == 0:
print(
"[green]Its recommended to run the following after updating:\n\tviu config --update (to get the latest config docs)\n\tviu cache --clean (to get rid of any potential issues)[/]",
file=sys.stderr,
)
return True, release_json
else:
return False, release_json