Ctrl K
ComunidadGuías…

ClipmanLinux/clipman-updater.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env python3
import argparse
import json
import os
import pathlib
import shutil
import subprocess
import time
import uuid


def process_exists(pid):
    try:
        os.kill(pid, 0)
        return True
    except ProcessLookupError:
        return False
    except PermissionError:
        return True


def write_result(path, value):
    path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
    temporary = path.with_suffix(".tmp")
    temporary.write_text(json.dumps(value) + "\n", encoding="utf-8")
    temporary.chmod(0o600)
    temporary.replace(path)


def relaunch(executable):
    systemd_run = shutil.which("systemd-run")
    if systemd_run and os.environ.get("DBUS_SESSION_BUS_ADDRESS"):
        unit = "clipman-linux-restart-" + uuid.uuid4().hex
        result = subprocess.run(
            [systemd_run, "--user", "--unit=" + unit, "--collect", executable],
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False,
        )
        if result.returncode == 0:
            return
    subprocess.Popen(
        [executable], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL, start_new_session=True,
    )


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--wait-pid", type=int, required=True)
    parser.add_argument("--package", type=pathlib.Path, required=True)
    parser.add_argument("--temporary", type=pathlib.Path, required=True)
    parser.add_argument("--launcher", required=True)
    parser.add_argument("--result", type=pathlib.Path, required=True)
    parser.add_argument("--version", required=True)
    args = parser.parse_args()
    deadline = time.monotonic() + 60
    while process_exists(args.wait_pid) and time.monotonic() < deadline:
        time.sleep(0.2)
    success = False
    error = ""
    try:
        if process_exists(args.wait_pid):
            raise RuntimeError("Clipman did not close before the update timeout.")
        completed = subprocess.run(
            [str(args.package / "install.sh")], cwd=args.package,
            text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
            timeout=120, check=False,
        )
        if completed.returncode != 0:
            raise RuntimeError((completed.stdout or "The installer failed.").strip()[-2000:])
        success = True
    except Exception as exception:
        error = str(exception)
    try:
        write_result(args.result, {"ok": success, "version": args.version, "error": error})
    except OSError:
        # A damaged result path must not strand Clipman in a closed state.
        pass
    try:
        relaunch(args.launcher)
    finally:
        shutil.rmtree(args.temporary, ignore_errors=True)
    return 0 if success else 1


if __name__ == "__main__":
    raise SystemExit(main())