- Updated version from 2026.05.31 to 2026.06.11 in setup.py - Replaced 'textual' with 'rich' in install_requires - Added privilege.py for managing sudo privileges with a keep-alive mechanism - Introduced process.py for handling subprocesses with enhanced control and output streaming - Created ui.py for unified console interactions and user prompts
118 lines
3.8 KiB
Python
118 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import List, Optional
|
|
|
|
from cobot import ui, process
|
|
from cobot.commands.local_setup import _ros2_env
|
|
|
|
_PROJECT_DIR = Path(__file__).parent.parent.parent
|
|
|
|
|
|
def _count_packages(packages: List[str], env: dict) -> int:
|
|
"""Count how many colcon packages will be built so we can show X / total progress.
|
|
Считает количество пакетов colcon для отображения прогресса X / всего.
|
|
"""
|
|
list_cmd = ["colcon", "list", "--base-paths", "src"]
|
|
if packages:
|
|
list_cmd += ["--packages-select"] + packages
|
|
result = subprocess.run(list_cmd, capture_output=True, text=True,
|
|
cwd=_PROJECT_DIR, env=env)
|
|
return max(len([l for l in result.stdout.splitlines() if l.strip()]), 1)
|
|
|
|
|
|
def _rebuild(packages: List[str], symlink: bool) -> None:
|
|
"""Run colcon build for the selected packages (or all), streaming live output
|
|
with a per-package progress bar.
|
|
Запускает colcon build для выбранных пакетов (или всех), транслируя живой вывод
|
|
с прогресс-баром по пакетам.
|
|
"""
|
|
env = _ros2_env()
|
|
total = _count_packages(packages, env)
|
|
|
|
pkg_label = " ".join(packages) if packages else "все пакеты"
|
|
symlink_label = " --symlink-install" if symlink else ""
|
|
|
|
cmd = ["colcon", "build", "--base-paths", "src"]
|
|
if symlink:
|
|
cmd.append("--symlink-install")
|
|
if packages:
|
|
cmd += ["--packages-select"] + packages
|
|
|
|
built = 0
|
|
|
|
def _parse(line: str):
|
|
nonlocal built
|
|
if "Finished <<<" in line or "Failed <<<" in line:
|
|
built += 1
|
|
return (built / total * 100, f"{built} / {total} пакетов")
|
|
return None
|
|
|
|
rc = process.run_step(
|
|
f"colcon build{symlink_label} — {pkg_label}",
|
|
cmd,
|
|
env=env,
|
|
cwd=str(_PROJECT_DIR),
|
|
total=100.0,
|
|
parse_progress=_parse,
|
|
success_msg="Сборка завершена",
|
|
fail_msg="Сборка завершилась с ошибкой",
|
|
)
|
|
if rc in (0, -9, -15):
|
|
ui.note("Активируйте окружение: source install/setup.bash")
|
|
|
|
|
|
def register(subparsers: argparse._SubParsersAction) -> None:
|
|
p = subparsers.add_parser(
|
|
"rebuild",
|
|
help="Rebuild ROS2 packages in src/ with colcon",
|
|
)
|
|
p.add_argument(
|
|
"packages",
|
|
nargs="*",
|
|
metavar="PACKAGE",
|
|
help="Packages to rebuild (omit to be asked, or leave empty for all)",
|
|
)
|
|
p.set_defaults(symlink=None)
|
|
p.add_argument(
|
|
"--symlink-install",
|
|
dest="symlink",
|
|
action="store_true",
|
|
help="Pass --symlink-install to colcon build",
|
|
)
|
|
p.add_argument(
|
|
"--no-symlink-install",
|
|
dest="symlink",
|
|
action="store_false",
|
|
help="Do not pass --symlink-install to colcon build",
|
|
)
|
|
p.set_defaults(func=run)
|
|
|
|
|
|
def run(args: argparse.Namespace) -> None:
|
|
"""Entry point for the rebuild command.
|
|
Точка входа для команды rebuild.
|
|
"""
|
|
packages: Optional[List[str]] = args.packages if args.packages else None
|
|
|
|
if packages is None:
|
|
value = ui.text(
|
|
"Какие пакеты пересобрать? (через пробел, пусто — все)",
|
|
"",
|
|
note="Пример: iiwa_controller iiwa_bringup",
|
|
)
|
|
if value is None:
|
|
return
|
|
packages = value.split() if value.strip() else []
|
|
|
|
symlink = args.symlink
|
|
if symlink is None:
|
|
choice = ui.select("Использовать --symlink-install?", ["Да", "Нет"], "Да")
|
|
if choice is None:
|
|
return
|
|
symlink = choice == "Да"
|
|
|
|
_rebuild(packages, symlink)
|