Files
lightweight-cobot/cobot/commands/update.py
T

111 lines
3.6 KiB
Python

from __future__ import annotations
import argparse
import subprocess
from pathlib import Path
from textual.app import App
from cobot.tui import SCREEN_CSS, LogScreen
_PROJECT_DIR = Path(__file__).parent.parent.parent
def _task_update(screen: LogScreen) -> None:
try:
# Current branch
branch = subprocess.check_output(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
cwd=_PROJECT_DIR, text=True,
).strip()
screen.write(f"[cyan][*][/cyan] Branch: [bold]{branch}[/bold]")
# Fetch (0 → 30 %)
screen.set_progress(0, "Fetching from remote...")
screen.write("[cyan][*][/cyan] Fetching from remote...")
fetch = subprocess.run(
["git", "fetch", "origin"],
cwd=_PROJECT_DIR, capture_output=True, text=True,
)
if fetch.returncode != 0:
screen.write(f"[red]Fetch failed:[/red] {fetch.stderr.strip()}")
screen.finish(False)
return
screen.set_progress(30)
# Check how many commits behind
behind = subprocess.check_output(
["git", "rev-list", f"HEAD..origin/{branch}", "--count"],
cwd=_PROJECT_DIR, text=True,
).strip()
if behind == "0":
screen.set_progress(100, "Already up to date")
screen.write("[green][ok][/green] Already up to date.")
screen.finish(True)
return
# Show incoming commits
screen.write(f"\n[bold]{behind} new commit(s):[/bold]")
log_lines = subprocess.check_output(
["git", "log", f"HEAD..origin/{branch}", "--oneline"],
cwd=_PROJECT_DIR, text=True,
).strip().splitlines()
for line in log_lines:
screen.write(f" [dim]{line}[/dim]")
# Pull (30 → 80 %)
screen.set_progress(30, "Pulling changes...")
screen.write("\n[cyan][*][/cyan] Pulling changes...")
pull = subprocess.run(
["git", "pull", "origin", branch],
capture_output=True, text=True, cwd=_PROJECT_DIR,
)
if pull.returncode != 0:
for line in (pull.stdout + pull.stderr).splitlines():
if line.strip():
screen.write(line)
screen.write("[red]Pull failed.[/red]")
screen.finish(False)
return
screen.set_progress(80)
# Reinstall (80 → 100 %)
screen.set_progress(80, "Reinstalling cobot CLI...")
screen.write("\n[cyan][*][/cyan] Reinstalling cobot CLI...")
reinstall = subprocess.run(
["uv", "tool", "install", "--editable", str(_PROJECT_DIR)],
capture_output=True, text=True,
)
if reinstall.returncode == 0:
screen.write("[green][ok][/green] cobot reinstalled")
else:
screen.write(f"[yellow]Warning:[/yellow] reinstall failed — {reinstall.stderr.strip()}")
screen.set_progress(100, "Done")
screen.write("\n[green]Project updated successfully.[/green]")
screen.finish(True)
except Exception as exc:
screen.write(f"\n[red]Error:[/red] {exc}")
screen.finish(False)
class _UpdateApp(App[None]):
CSS = SCREEN_CSS
def on_mount(self) -> None:
self.push_screen(
LogScreen("Updating project", _task_update, show_progress=True),
lambda _: self.exit(),
)
def register(subparsers: argparse._SubParsersAction) -> None:
p = subparsers.add_parser("update", help="Pull latest changes from the remote git branch")
p.set_defaults(func=run)
def run(args: argparse.Namespace) -> None:
_UpdateApp().run()