Compare commits

...

14 Commits

Author SHA1 Message Date
dw-0
4657b7830c Merge branch 'master' into kiauh-v6-dev 2024-08-31 17:46:41 +02:00
dw-0
372ffeb754 refactor(extension): set margin to 1 for dialog
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 17:27:18 +02:00
dw-0
a9a23304c7 refactor: set new default of margin to 0 in Logger.print_dialog()
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 17:22:10 +02:00
dw-0
ea6eef984f chore(extension): remove debug print
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 17:07:02 +02:00
dw-0
5d2b9e4671 refactor: remove remaining deprecated arguments from Option class
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 16:53:26 +02:00
dw-0
fee52551c7 refactor: show actual version in main menu
filter tags to v5 in kiauh bash version

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 12:39:41 +02:00
Henrik Fransson
8547942986 readme: fix broken OctoApp plugin link (#494) 2024-08-06 16:41:18 +02:00
dw-0
d33ac6b15a fix: parse moonraker dependencies from system-dependencies.json (#492)
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-03 13:30:34 +02:00
dw-0
6cd9133a15 fix: detect RatOS 2.1+ as operating system and exit (#490)
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-07-31 20:30:33 +02:00
Beans Baxter
a929c6983d refactor: don't check spoolman version if not installed (#487) 2024-06-28 23:07:20 +02:00
breakheart
bce92001a6 fix: use correct Spoolman directory name (#486) 2024-06-28 17:46:19 +02:00
Alessandro Maggi
7993b98ee1 fix: replace jq by grep to check Spoolman update (#482)
* fix: remove extra space in remove menu

* fix(spoolman): replace jq with grep
jq isn't included in some minimal installations
2024-06-26 07:04:09 +02:00
Alessandro Maggi
62296e112e feat: add Spoolman support (#477) 2024-06-25 20:10:14 +02:00
Justin Otherguy
a374ac8fac fix: add unzip to dependencies for Mainsail and Fluidd 2024-05-09 20:56:16 +02:00
21 changed files with 103 additions and 58 deletions

View File

@@ -164,7 +164,6 @@ function main() {
fi
}
check_if_ratos
check_euid
init_logfile
@@ -173,4 +172,3 @@ kiauh_update_dialog
read_kiauh_ini
init_ini
main

View File

@@ -234,8 +234,6 @@ def display_moonraker_info(moonraker_list: List[Moonraker]) -> bool:
"The following Klipper instances will be installed:",
*[f"● klipper-{m.suffix}" for m in moonraker_list],
],
padding_top=0,
padding_bottom=0,
)
_input: bool = get_confirm("Proceed with installation?")
return _input

View File

@@ -103,7 +103,6 @@ def check_user_groups() -> None:
"INFO:",
"Relog required for group assignments to take effect!",
],
padding_bottom=0,
)
if not get_confirm(f"Add user '{CURRENT_USER}' to group(s) now?"):

View File

@@ -32,7 +32,7 @@ class KlipperNoFirmwareErrorMenu(BaseMenu):
self.previous_menu = previous_menu
def set_options(self) -> None:
self.default_option = Option(self.go_back, False)
self.default_option = Option(method=self.go_back)
def print_menu(self) -> None:
header = "!!! NO FIRMWARE FILE FOUND !!!"
@@ -79,7 +79,7 @@ class KlipperNoBoardTypesErrorMenu(BaseMenu):
self.previous_menu = previous_menu
def set_options(self) -> None:
self.default_option = Option(self.go_back, False)
self.default_option = Option(method=self.go_back)
def print_menu(self) -> None:
header = "!!! ERROR GETTING BOARD LIST !!!"

View File

@@ -260,8 +260,7 @@ class KlipperSelectMcuIdMenu(BaseMenu):
def set_options(self) -> None:
self.options = {
f"{i}": Option(self.flash_mcu, False, f"{i}")
for i in range(len(self.mcu_list))
f"{i}": Option(self.flash_mcu, f"{i}") for i in range(len(self.mcu_list))
}
def print_menu(self) -> None:
@@ -323,7 +322,7 @@ class KlipperSelectSDFlashBoardMenu(BaseMenu):
def set_options(self) -> None:
self.options = {
f"{i}": Option(self.board_select, False, f"{i}")
f"{i}": Option(self.board_select, f"{i}")
for i in range(len(self.available_boards))
}

View File

@@ -68,8 +68,6 @@ def install_klipperscreen() -> None:
"KlipperScreens update manager configuration for Moonraker "
"will not be added to any moonraker.conf.",
],
padding_top=0,
padding_bottom=0,
)
if not get_confirm(
"Continue KlipperScreen installation?",

View File

@@ -32,7 +32,7 @@ class LogUploadMenu(BaseMenu):
def set_options(self) -> None:
self.options = {
f"{index}": Option(self.upload, False, opt_index=f"{index}")
f"{index}": Option(self.upload, opt_index=f"{index}")
for index in range(len(self.logfile_list))
}

View File

@@ -63,8 +63,6 @@ def install_octoeverywhere() -> None:
"It is safe to run the installer again to link your "
"printer or repair any issues.",
],
padding_top=0,
padding_bottom=0,
)
if not get_confirm("Re-run OctoEverywhere installation?"):
Logger.print_info("Exiting OctoEverywhere for Klipper installation ...")
@@ -85,8 +83,6 @@ def install_octoeverywhere() -> None:
"\n\n",
"The setup will apply the same names to OctoEverywhere!",
],
padding_top=0,
padding_bottom=0,
)
if not get_confirm(

View File

@@ -24,8 +24,6 @@ def print_moonraker_not_found_dialog() -> None:
"another machine in your network. Otherwise Mainsail will NOT work "
"correctly.",
],
padding_top=0,
padding_bottom=0,
)
@@ -36,8 +34,6 @@ def print_client_already_installed_dialog(name: str) -> None:
f"{name} seems to be already installed!",
f"If you continue, your current {name} installation will be overwritten.",
],
padding_top=0,
padding_bottom=0,
)
@@ -57,8 +53,6 @@ def print_client_port_select_dialog(
"The following ports were found to be in use already:",
*[f"{port}" for port in ports_in_use],
],
padding_top=0,
padding_bottom=0,
)
@@ -77,8 +71,6 @@ def print_install_client_config_dialog(client: BaseWebClient) -> None:
"If you already use these macros skip this step. Otherwise you should "
"consider to answer with 'Y' to download the recommended macros.",
],
padding_top=0,
padding_bottom=0,
)

View File

@@ -38,7 +38,7 @@ from core.types import ComponentStatus
from utils.common import get_install_status
from utils.fs_utils import create_symlink, remove_file
from utils.git_utils import (
get_latest_tag,
get_latest_remote_tag,
get_latest_unstable_tag,
)
@@ -137,7 +137,7 @@ def get_local_client_version(client: BaseWebClient) -> str | None:
def get_remote_client_version(client: BaseWebClient) -> str | None:
try:
if (tag := get_latest_tag(client.repo_path)) != "":
if (tag := get_latest_remote_tag(client.repo_path)) != "":
return str(tag)
return None
except Exception:

View File

@@ -92,8 +92,8 @@ class Logger:
center_content: bool = False,
custom_title: str | None = None,
custom_color: DialogCustomColor | None = None,
padding_top: int = 1,
padding_bottom: int = 1,
margin_top: int = 0,
margin_bottom: int = 0,
) -> None:
"""
Prints a dialog with the given title and content.
@@ -106,8 +106,8 @@ class Logger:
:param center_content: Whether to center the content or not.
:param custom_title: A custom title for the dialog.
:param custom_color: A custom color for the dialog.
:param padding_top: The number of empty lines to print before the dialog.
:param padding_bottom: The number of empty lines to print after the dialog.
:param margin_top: The number of empty lines to print before the dialog.
:param margin_bottom: The number of empty lines to print after the dialog.
"""
dialog_color = Logger._get_dialog_color(title, custom_color)
dialog_title = Logger._get_dialog_title(title, custom_title)
@@ -116,12 +116,12 @@ class Logger:
top = Logger._format_top_border(dialog_color)
bottom = Logger._format_bottom_border()
print("\n" * padding_top)
print("\n" * margin_top)
print(
f"{top}{dialog_title_formatted}{dialog_content}{bottom}",
end="",
)
print("\n" * padding_bottom)
print("\n" * margin_bottom)
@staticmethod
def _get_dialog_title(

View File

@@ -10,7 +10,7 @@ from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import Any, Callable
from typing import Any, Callable, Type
@dataclass
@@ -22,7 +22,7 @@ class Option:
:param opt_data: Can be used to pass any additional data to the menu option
"""
method: Callable | None = None
method: Type[Callable] | None = None
opt_index: str = ""
opt_data: Any = None

View File

@@ -44,6 +44,7 @@ from core.menus.settings_menu import SettingsMenu
from core.menus.update_menu import UpdateMenu
from core.types import ComponentStatus, StatusMap, StatusText
from extensions.extensions_menu import ExtensionsMenu
from utils.common import get_kiauh_version
# noinspection PyUnusedLocal
@@ -55,6 +56,7 @@ class MainMenu(BaseMenu):
self.header: bool = True
self.footer_type: FooterType = FooterType.QUIT
self.version = ""
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.cc_status = self.oe_status = ""
@@ -86,6 +88,7 @@ class MainMenu(BaseMenu):
)
def _fetch_status(self) -> None:
self.version = get_kiauh_version()
self._get_component_status("kl", get_klipper_status)
self._get_component_status("mr", get_moonraker_status)
self._get_component_status("ms", get_client_status, MainsailData())
@@ -125,7 +128,7 @@ class MainMenu(BaseMenu):
self._fetch_status()
header = " [ Main Menu ] "
footer1 = f"{COLOR_CYAN}KIAUH v6.0.0{RESET_FORMAT}"
footer1 = f"{COLOR_CYAN}{self.version}{RESET_FORMAT}"
footer2 = f"Changelog: {COLOR_MAGENTA}https://git.io/JnmlX{RESET_FORMAT}"
color = COLOR_CYAN
count = 62 - len(color) - len(RESET_FORMAT)

View File

@@ -281,8 +281,6 @@ class UpdateMenu(BaseMenu):
DialogType.CUSTOM,
["The following packages will be upgraded:", "\n\n", pkgs],
custom_title="UPGRADABLE SYSTEM UPDATES",
padding_top=0,
padding_bottom=0,
)
if not get_confirm("Continue?"):
return

View File

@@ -38,9 +38,7 @@ class ExtensionsMenu(BaseMenu):
def set_options(self) -> None:
self.options = {
i: Option(
self.extension_submenu, menu=True, opt_data=self.extensions.get(i)
)
i: Option(self.extension_submenu, opt_data=self.extensions.get(i))
for i in self.extensions
}

View File

@@ -93,7 +93,7 @@ class MainsailThemeInstallMenu(BaseMenu):
def set_options(self) -> None:
self.options = {
f"{index}": Option(self.install_theme, False, opt_index=f"{index}")
f"{index}": Option(self.install_theme, opt_index=f"{index}")
for index in range(len(self.themes))
}

View File

@@ -49,8 +49,6 @@ class TelegramBotExtension(BaseExtension):
"Moonraker Telegram Bot requires Moonraker to be installed. "
"Please install Moonraker first!",
],
padding_top=0,
padding_bottom=0,
)
return
@@ -65,8 +63,6 @@ class TelegramBotExtension(BaseExtension):
"\n\n",
"The setup will apply the same names to Telegram Bot!",
],
padding_top=0,
padding_bottom=0,
)
if not get_confirm(
"Continue Moonraker Telegram Bot installation?",
@@ -88,8 +84,6 @@ class TelegramBotExtension(BaseExtension):
instance = MoonrakerTelegramBot(suffix=name)
instance.create()
print(instance)
cmd_sysctl_service(instance.service_file_path.name, "enable")
if create_example_cfg:
@@ -126,6 +120,7 @@ class TelegramBotExtension(BaseExtension):
"following wiki page for further information:",
"https://github.com/nlef/moonraker-telegram-bot/wiki",
],
margin_bottom=1,
)
Logger.print_ok("Telegram Bot installation complete!")

View File

@@ -35,8 +35,6 @@ def change_system_hostname() -> None:
"browser.",
],
custom_title="CHANGE SYSTEM HOSTNAME",
padding_top=0,
padding_bottom=0,
)
if not get_confirm("Do you want to change the hostname?", default_choice=False):
return
@@ -50,8 +48,6 @@ def change_system_hostname() -> None:
"● Any special characters",
"● No leading or trailing '-'",
],
padding_top=0,
padding_bottom=0,
)
hostname = get_string_input(
"Enter the new hostname",

View File

@@ -22,7 +22,12 @@ from core.constants import (
)
from core.logger import DialogType, Logger
from core.types import ComponentStatus, StatusCode
from utils.git_utils import get_local_commit, get_remote_commit, get_repo_name
from utils.git_utils import (
get_local_commit,
get_local_tags,
get_remote_commit,
get_repo_name,
)
from utils.instance_utils import get_instances
from utils.sys_utils import (
check_package_install,
@@ -31,6 +36,14 @@ from utils.sys_utils import (
)
def get_kiauh_version() -> str:
"""
Helper method to get the current KIAUH version by reading the latest tag
:return: string of the latest tag
"""
return get_local_tags(Path(__file__).parent.parent)[-1]
def convert_camelcase_to_kebabcase(name: str) -> str:
return re.sub(r"(?<!^)(?=[A-Z])", "-", name).lower()

View File

@@ -84,7 +84,38 @@ def get_repo_name(repo: Path) -> str | None:
return None
def get_tags(repo_path: str) -> List[str]:
def get_local_tags(repo_path: Path, _filter: str | None = None) -> List[str]:
"""
Get all tags of a local Git repository
:param repo_path: Path to the local Git repository
:param _filter: Optional filter to filter the tags by
:return: List of tags
"""
try:
cmd = ["git", "tag", "-l"]
if _filter is not None:
cmd.append(f"'${_filter}'")
result: str = check_output(
cmd,
stderr=DEVNULL,
cwd=repo_path.as_posix(),
).decode(encoding="utf-8")
tags = result.split("\n")
return tags[:-1]
except CalledProcessError:
return []
def get_remote_tags(repo_path: str) -> List[str]:
"""
Gets the tags of a GitHub repostiory
:param repo_path: path of the GitHub repository - e.g. `<owner>/<name>`
:return: List of tags
"""
try:
url = f"https://api.github.com/repos/{repo_path}/tags"
with urllib.request.urlopen(url) as r:
@@ -102,14 +133,14 @@ def get_tags(repo_path: str) -> List[str]:
raise
def get_latest_tag(repo_path: str) -> str:
def get_latest_remote_tag(repo_path: str) -> str:
"""
Gets the latest stable tag of a GitHub repostiory
:param repo_path: path of the GitHub repository - e.g. `<owner>/<name>`
:return: tag or empty string
"""
try:
if len(latest_tag := get_tags(repo_path)) > 0:
if len(latest_tag := get_remote_tags(repo_path)) > 0:
return latest_tag[0]
else:
return ""
@@ -124,7 +155,10 @@ def get_latest_unstable_tag(repo_path: str) -> str:
:return: tag or empty string
"""
try:
if len(unstable_tags := [t for t in get_tags(repo_path) if "-" in t]) > 0:
if (
len(unstable_tags := [t for t in get_remote_tags(repo_path) if "-" in t])
> 0
):
return unstable_tags[0]
else:
return ""
@@ -133,6 +167,34 @@ def get_latest_unstable_tag(repo_path: str) -> str:
raise
def compare_semver_tags(tag1: str, tag2: str) -> bool:
"""
Compare two semver version strings.
Does not support comparing pre-release versions (e.g. 1.0.0-rc.1, 1.0.0-beta.1)
:param tag1: First version string
:param tag2: Second version string
:return: True if tag1 is greater than tag2, False otherwise
"""
if tag1 == tag2:
return False
def parse_version(v):
return list(map(int, v[1:].split(".")))
tag1_parts = parse_version(tag1)
tag2_parts = parse_version(tag2)
max_len = max(len(tag1_parts), len(tag2_parts))
tag1_parts += [0] * (max_len - len(tag1_parts))
tag2_parts += [0] * (max_len - len(tag2_parts))
for part1, part2 in zip(tag1_parts, tag2_parts):
if part1 != part2:
return part1 > part2
return False
def get_local_commit(repo: Path) -> str | None:
if not repo.exists() or not repo.joinpath(".git").exists():
return None

View File

@@ -40,7 +40,7 @@ function main_ui() {
function get_kiauh_version() {
local version
cd "${KIAUH_SRCDIR}"
version="$(git describe HEAD --always --tags | cut -d "-" -f 1,2)"
version="$(git tag -l 'v5*' | tail -1)"
echo "${version}"
}