104 lines
3.2 KiB
Python
104 lines
3.2 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
|
|
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
|
|
|
|
# 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.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
|
|
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
|
|
|
|
# Reinstall in case dependencies changed
|
|
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.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),
|
|
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()
|