From dfbce3b489d3c83255f888ccf66e9f9462a36484 Mon Sep 17 00:00:00 2001 From: dw-0 Date: Thu, 28 Dec 2023 13:38:24 +0100 Subject: [PATCH] feat(KIAUH): show commit in UpdateMenu Signed-off-by: Dominik Willner --- kiauh/core/menus/main_menu.py | 57 +++++++++++----- kiauh/core/menus/update_menu.py | 76 +++++++++++++++------- kiauh/core/repo_manager/repo_manager.py | 40 ++++++++++++ kiauh/modules/klipper/klipper_utils.py | 19 ++++-- kiauh/modules/moonraker/moonraker_utils.py | 23 +++++-- kiauh/utils/common.py | 40 +++++------- 6 files changed, 182 insertions(+), 73 deletions(-) diff --git a/kiauh/core/menus/main_menu.py b/kiauh/core/menus/main_menu.py index b62b312..4f1579f 100644 --- a/kiauh/core/menus/main_menu.py +++ b/kiauh/core/menus/main_menu.py @@ -21,7 +21,14 @@ from kiauh.core.menus.update_menu import UpdateMenu from kiauh.modules.klipper.klipper_utils import get_klipper_status from kiauh.modules.mainsail.mainsail_utils import get_mainsail_status from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status -from kiauh.utils.constants import COLOR_MAGENTA, COLOR_CYAN, RESET_FORMAT, COLOR_RED +from kiauh.utils.constants import ( + COLOR_MAGENTA, + COLOR_CYAN, + RESET_FORMAT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW, +) class MainMenu(BaseMenu): @@ -39,18 +46,18 @@ class MainMenu(BaseMenu): }, footer_type=QUIT_FOOTER, ) - self.kl_status = None - self.kl_repo = None - self.mr_status = None - self.mr_repo = None - self.ms_status = None - self.fl_status = None - self.ks_status = None - self.mb_status = None - self.cn_status = None - self.tg_status = None - self.ob_status = None - self.oe_status = None + self.kl_status = "" + self.kl_repo = "" + self.mr_status = "" + self.mr_repo = "" + self.ms_status = "" + self.fl_status = "" + self.ks_status = "" + self.mb_status = "" + self.cn_status = "" + self.tg_status = "" + self.ob_status = "" + self.oe_status = "" self.init_status() def init_status(self) -> None: @@ -60,14 +67,30 @@ class MainMenu(BaseMenu): def fetch_status(self) -> None: # klipper - self.kl_status = get_klipper_status().get("status") - self.kl_repo = get_klipper_status().get("repo") + klipper_status = get_klipper_status() + kl_status = klipper_status.get("status") + kl_code = klipper_status.get("status_code") + kl_instances = f" {klipper_status.get('instances')}" if kl_code == 1 else "" + self.kl_status = self.format_status_by_code(kl_code, kl_status, kl_instances) + self.kl_repo = f"{COLOR_CYAN}{klipper_status.get('repo')}{RESET_FORMAT}" # moonraker - self.mr_status = get_moonraker_status().get("status") - self.mr_repo = get_moonraker_status().get("repo") + moonraker_status = get_moonraker_status() + mr_status = moonraker_status.get("status") + mr_code = moonraker_status.get("status_code") + mr_instances = f" {moonraker_status.get('instances')}" if mr_code == 1 else "" + self.mr_status = self.format_status_by_code(mr_code, mr_status, mr_instances) + self.mr_repo = f"{COLOR_CYAN}{moonraker_status.get('repo')}{RESET_FORMAT}" # mainsail self.ms_status = get_mainsail_status() + def format_status_by_code(self, code: int, status: str, count: str) -> str: + if code == 1: + return f"{COLOR_GREEN}{status}{count}{RESET_FORMAT}" + elif code == 2: + return f"{COLOR_RED}{status}{count}{RESET_FORMAT}" + + return f"{COLOR_YELLOW}{status}{count}{RESET_FORMAT}" + def print_menu(self): self.fetch_status() diff --git a/kiauh/core/menus/update_menu.py b/kiauh/core/menus/update_menu.py index 3413616..21da09b 100644 --- a/kiauh/core/menus/update_menu.py +++ b/kiauh/core/menus/update_menu.py @@ -14,7 +14,11 @@ import textwrap from kiauh.core.menus import BACK_FOOTER from kiauh.core.menus.base_menu import BaseMenu from kiauh.modules.klipper.klipper_setup import update_klipper -from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT +from kiauh.modules.klipper.klipper_utils import ( + get_klipper_status, +) +from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status +from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT, COLOR_YELLOW, COLOR_WHITE # noinspection PyMethodMayBeStatic @@ -39,8 +43,14 @@ class UpdateMenu(BaseMenu): }, footer_type=BACK_FOOTER, ) + self.kl_local = f"{COLOR_WHITE}{RESET_FORMAT}" + self.kl_remote = f"{COLOR_WHITE}{RESET_FORMAT}" + self.mr_local = f"{COLOR_WHITE}{RESET_FORMAT}" + self.mr_remote = f"{COLOR_WHITE}{RESET_FORMAT}" def print_menu(self): + self.fetch_update_status() + header = " [ Update Menu ] " color = COLOR_GREEN count = 62 - len(color) - len(RESET_FORMAT) @@ -49,28 +59,28 @@ class UpdateMenu(BaseMenu): /=======================================================\\ | {color}{header:~^{count}}{RESET_FORMAT} | |-------------------------------------------------------| - | 0) [Update all] | | | - | | Current: | Latest: | - | Klipper & API: |--------------|--------------| - | 1) [Klipper] | | | - | 2) [Moonraker] | | | - | | | | - | Klipper Webinterface: |--------------|--------------| - | 3) [Mainsail] | | | - | 4) [Fluidd] | | | - | | | | - | Touchscreen GUI: |--------------|--------------| - | 5) [KlipperScreen] | | | - | | | | - | Other: |--------------|--------------| - | 6) [PrettyGCode] | | | - | 7) [Telegram Bot] | | | - | 8) [Obico for Klipper] | | | - | 9) [OctoEverywhere] | | | - | 10) [Mobileraker] | | | - | 11) [Crowsnest] | | | - | |-----------------------------| - | 12) [System] | | | + | 0) Update all | | | + | | Current: | Latest: | + | Klipper & API: |---------------|---------------| + | 1) Klipper | {self.kl_local:<22} | {self.kl_remote:<22} | + | 2) Moonraker | {self.mr_local:<22} | {self.mr_remote:<22} | + | | | | + | Klipper Webinterface: |---------------|---------------| + | 3) Mainsail | | | + | 4) Fluidd | | | + | | | | + | Touchscreen GUI: |---------------|---------------| + | 5) KlipperScreen | | | + | | | | + | Other: |---------------|---------------| + | 6) PrettyGCode | | | + | 7) Telegram Bot | | | + | 8) Obico for Klipper | | | + | 9) OctoEverywhere | | | + | 10) Mobileraker | | | + | 11) Crowsnest | | | + | |-------------------------------| + | 12) System | | """ )[1:] print(menu, end="") @@ -113,3 +123,23 @@ class UpdateMenu(BaseMenu): def upgrade_system_packages(self): print("upgrade_system_packages") + + def fetch_update_status(self): + # klipper + kl_status = get_klipper_status() + self.kl_local = kl_status.get("local") + self.kl_remote = kl_status.get("remote") + if self.kl_local == self.kl_remote: + self.kl_local = f"{COLOR_GREEN}{self.kl_local}{RESET_FORMAT}" + else: + self.kl_local = f"{COLOR_YELLOW}{self.kl_local}{RESET_FORMAT}" + self.kl_remote = f"{COLOR_GREEN}{self.kl_remote}{RESET_FORMAT}" + # moonraker + mr_status = get_moonraker_status() + self.mr_local = mr_status.get("local") + self.mr_remote = mr_status.get("remote") + if self.mr_local == self.mr_remote: + self.mr_local = f"{COLOR_GREEN}{self.mr_local}{RESET_FORMAT}" + else: + self.mr_local = f"{COLOR_YELLOW}{self.mr_local}{RESET_FORMAT}" + self.mr_remote = f"{COLOR_GREEN}{self.mr_remote}{RESET_FORMAT}" diff --git a/kiauh/core/repo_manager/repo_manager.py b/kiauh/core/repo_manager/repo_manager.py index a3343e8..61250c4 100644 --- a/kiauh/core/repo_manager/repo_manager.py +++ b/kiauh/core/repo_manager/repo_manager.py @@ -62,6 +62,46 @@ class RepoManager: def target_dir(self, value) -> None: self._target_dir = value + @staticmethod + def get_repo_name(repo: Path) -> str: + """ + Helper method to extract the organisation and name of a repository | + :param repo: repository to extract the values from + :return: String in form of "/" + """ + try: + cmd = ["git", "-C", repo, "config", "--get", "remote.origin.url"] + result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) + return "/".join(result.decode().strip().split("/")[-2:]) + except subprocess.CalledProcessError: + return "-" + + @staticmethod + def get_local_commit(repo: Path) -> str: + if not repo.exists() and repo.joinpath(".git").exists(): + return "-" + + try: + cmd = f"cd {repo} && git describe HEAD --always --tags | cut -d '-' -f 1,2" + return subprocess.check_output(cmd, shell=True, text=True).strip() + except subprocess.CalledProcessError: + return "-" + + @staticmethod + def get_remote_commit(repo: Path) -> str: + if not repo.exists() and repo.joinpath(".git").exists(): + return "-" + + try: + # get locally checked out branch + branch_cmd = f"cd {repo} && git branch | grep -E '\*'" + branch = subprocess.check_output(branch_cmd, shell=True, text=True) + branch = branch.split("*")[-1].strip() + cmd = f"cd {repo} && git describe 'origin/{branch}' --always --tags | cut -d '-' -f 1,2" + return subprocess.check_output(cmd, shell=True, text=True).strip() + except subprocess.CalledProcessError: + return "-" + def clone_repo(self): log = f"Cloning repository from '{self.repo}' with method '{self.method}'" Logger.print_status(log) diff --git a/kiauh/modules/klipper/klipper_utils.py b/kiauh/modules/klipper/klipper_utils.py index 67818dd..3aae6b9 100644 --- a/kiauh/modules/klipper/klipper_utils.py +++ b/kiauh/modules/klipper/klipper_utils.py @@ -23,6 +23,7 @@ from kiauh.core.config_manager.config_manager import ConfigManager from kiauh.core.instance_manager.base_instance import BaseInstance from kiauh.core.instance_manager.instance_manager import InstanceManager from kiauh.core.instance_manager.name_scheme import NameScheme +from kiauh.core.repo_manager.repo_manager import RepoManager from kiauh.modules.klipper import MODULE_PATH, KLIPPER_DIR, KLIPPER_ENV_DIR from kiauh.modules.klipper.klipper import Klipper from kiauh.modules.klipper.klipper_dialogs import ( @@ -33,17 +34,27 @@ from kiauh.modules.klipper.klipper_dialogs import ( ) from kiauh.modules.moonraker.moonraker import Moonraker from kiauh.modules.moonraker.moonraker_utils import moonraker_to_multi_conversion -from kiauh.utils.common import get_install_status_common, get_repo_name +from kiauh.utils.common import get_install_status_common from kiauh.utils.constants import CURRENT_USER from kiauh.utils.input_utils import get_confirm, get_string_input, get_number_input from kiauh.utils.logger import Logger from kiauh.utils.system_utils import mask_system_service -def get_klipper_status() -> Dict[Literal["status", "repo"], str]: +def get_klipper_status() -> ( + Dict[ + Literal["status", "status_code", "instances", "repo", "local", "remote"], + Union[str, int], + ] +): + status = get_install_status_common(Klipper, KLIPPER_DIR, KLIPPER_ENV_DIR) return { - "status": get_install_status_common(Klipper, KLIPPER_DIR, KLIPPER_ENV_DIR), - "repo": get_repo_name(KLIPPER_DIR), + "status": status.get("status"), + "status_code": status.get("status_code"), + "instances": status.get("instances"), + "repo": RepoManager.get_repo_name(KLIPPER_DIR), + "local": RepoManager.get_local_commit(KLIPPER_DIR), + "remote": RepoManager.get_remote_commit(KLIPPER_DIR), } diff --git a/kiauh/modules/moonraker/moonraker_utils.py b/kiauh/modules/moonraker/moonraker_utils.py index c92721f..c0e1e81 100644 --- a/kiauh/modules/moonraker/moonraker_utils.py +++ b/kiauh/modules/moonraker/moonraker_utils.py @@ -10,10 +10,11 @@ # ======================================================================= # import shutil -from typing import Dict, Literal, List +from typing import Dict, Literal, List, Union from kiauh.core.config_manager.config_manager import ConfigManager from kiauh.core.instance_manager.instance_manager import InstanceManager +from kiauh.core.repo_manager.repo_manager import RepoManager from kiauh.modules.mainsail import MAINSAIL_DIR from kiauh.modules.mainsail.mainsail_utils import enable_mainsail_remotemode from kiauh.modules.moonraker import ( @@ -23,19 +24,27 @@ from kiauh.modules.moonraker import ( MOONRAKER_ENV_DIR, ) from kiauh.modules.moonraker.moonraker import Moonraker -from kiauh.utils.common import get_install_status_common, get_repo_name +from kiauh.utils.common import get_install_status_common from kiauh.utils.logger import Logger from kiauh.utils.system_utils import ( get_ipv4_addr, ) -def get_moonraker_status() -> Dict[Literal["status", "repo"], str]: +def get_moonraker_status() -> ( + Dict[ + Literal["status", "status_code", "instances", "repo", "local", "remote"], + Union[str, int], + ] +): + status = get_install_status_common(Moonraker, MOONRAKER_DIR, MOONRAKER_ENV_DIR) return { - "status": get_install_status_common( - Moonraker, MOONRAKER_DIR, MOONRAKER_ENV_DIR - ), - "repo": get_repo_name(MOONRAKER_DIR), + "status": status.get("status"), + "status_code": status.get("status_code"), + "instances": status.get("instances"), + "repo": RepoManager.get_repo_name(MOONRAKER_DIR), + "local": RepoManager.get_local_commit(MOONRAKER_DIR), + "remote": RepoManager.get_remote_commit(MOONRAKER_DIR), } diff --git a/kiauh/utils/common.py b/kiauh/utils/common.py index aebbaf3..ee8739c 100644 --- a/kiauh/utils/common.py +++ b/kiauh/utils/common.py @@ -9,10 +9,9 @@ # This file may be distributed under the terms of the GNU GPLv3 license # # ======================================================================= # -import subprocess from datetime import datetime from pathlib import Path -from typing import Dict, Literal, List, Type +from typing import Dict, Literal, List, Type, Union from kiauh.core.instance_manager.base_instance import BaseInstance from kiauh.core.instance_manager.instance_manager import InstanceManager @@ -56,24 +55,9 @@ def check_install_dependencies(deps: List[str]) -> None: install_system_packages(requirements) -def get_repo_name(repo_dir: Path) -> str: - """ - Helper method to extract the organisation and name of a repository | - :param repo_dir: repository to extract the values from - :return: String in form of "/" - """ - try: - cmd = ["git", "-C", repo_dir, "config", "--get", "remote.origin.url"] - result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) - result = "/".join(result.decode().strip().split("/")[-2:]) - return f"{COLOR_CYAN}{result}{RESET_FORMAT}" - except subprocess.CalledProcessError: - return f"{COLOR_RED}-{RESET_FORMAT}" - - def get_install_status_common( instance_type: Type[BaseInstance], repo_dir: Path, env_dir: Path -) -> str: +) -> Dict[Literal["status", "status_code", "instances"], Union[str, int]]: """ Helper method to get the installation status of software components, which only consist of 3 major parts and if those parts exist, the @@ -82,17 +66,29 @@ def get_install_status_common( :param instance_type: The component type :param repo_dir: the repository directory :param env_dir: the python environment directory - :return: formatted string, containing the status + :return: Dictionary with status string, statuscode and instance count """ im = InstanceManager(instance_type) instances_exist = len(im.instances) > 0 status = [repo_dir.exists(), env_dir.exists(), instances_exist] if all(status): - return f"{COLOR_GREEN}Installed: {len(im.instances)}{RESET_FORMAT}" + return { + "status": "Installed:", + "status_code": 1, + "instances": len(im.instances), + } elif not any(status): - return f"{COLOR_RED}Not installed!{RESET_FORMAT}" + return { + "status": "Not installed!", + "status_code": 2, + "instances": len(im.instances), + } else: - return f"{COLOR_YELLOW}Incomplete!{RESET_FORMAT}" + return { + "status": "Incomplete!", + "status_code": 3, + "instances": len(im.instances), + } def get_install_status_webui(