mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-24 00:03:42 +05:00
Compare commits
16 Commits
v5.1.9
...
2d3548b5f3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d3548b5f3 | ||
|
|
6c81ba2232 | ||
|
|
a777461296 | ||
|
|
2c045bb647 | ||
|
|
a21e059328 | ||
|
|
6853e97fb8 | ||
|
|
837488e4dd | ||
|
|
68cc03f3d0 | ||
|
|
606686b33c | ||
|
|
fc494e21da | ||
|
|
41fccb88fd | ||
|
|
66975cd913 | ||
|
|
89ad92468d | ||
|
|
ef44ba8253 | ||
|
|
d41865e693 | ||
|
|
ba594355ba |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,4 +10,3 @@ __pycache__
|
|||||||
*.code-workspace
|
*.code-workspace
|
||||||
*.iml
|
*.iml
|
||||||
kiauh.cfg
|
kiauh.cfg
|
||||||
klipper_repos.txt
|
|
||||||
|
|||||||
3
.vs/ProjectSettings.json
Normal file
3
.vs/ProjectSettings.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"CurrentProjectSetting": null
|
||||||
|
}
|
||||||
11
.vs/VSWorkspaceState.json
Normal file
11
.vs/VSWorkspaceState.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ExpandedNodes": [
|
||||||
|
"",
|
||||||
|
"\\kiauh",
|
||||||
|
"\\kiauh\\components\\droidklipp",
|
||||||
|
"\\kiauh\\core",
|
||||||
|
"\\kiauh\\core\\menus"
|
||||||
|
],
|
||||||
|
"SelectedNode": "\\kiauh\\core\\menus\\main_menu.py",
|
||||||
|
"PreviewInSolutionExplorer": false
|
||||||
|
}
|
||||||
BIN
.vs/kiauhPlusDroidKlipp/v16/.suo
Normal file
BIN
.vs/kiauhPlusDroidKlipp/v16/.suo
Normal file
Binary file not shown.
BIN
.vs/slnx.sqlite
Normal file
BIN
.vs/slnx.sqlite
Normal file
Binary file not shown.
@@ -71,14 +71,14 @@ sudo apt-get update && sudo apt-get install git -y
|
|||||||
Once git is installed, use the following command to download KIAUH into your home-directory:
|
Once git is installed, use the following command to download KIAUH into your home-directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd ~ && git clone https://github.com/dw-0/kiauh.git
|
cd ~ && git clone https://github.com/CodeMasterCody3D/kiauhPlusDroidKlipp.git
|
||||||
```
|
```
|
||||||
|
|
||||||
* **Step 3:** \
|
* **Step 3:** \
|
||||||
Finally, start KIAUH by running the next command:
|
Finally, start KIAUH by running the next command:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./kiauh/kiauh.sh
|
./kiauhPlusDroidKlipp/kiauh.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
* **Step 4:** \
|
* **Step 4:** \
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
from core.constants import SYSTEMD
|
from core.constants import SYSTEMD
|
||||||
|
|
||||||
# repo
|
# repo
|
||||||
@@ -19,6 +20,7 @@ CROWSNEST_SERVICE_NAME = "crowsnest.service"
|
|||||||
|
|
||||||
# directories
|
# directories
|
||||||
CROWSNEST_DIR = Path.home().joinpath("crowsnest")
|
CROWSNEST_DIR = Path.home().joinpath("crowsnest")
|
||||||
|
CROWSNEST_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("crowsnest-backups")
|
||||||
|
|
||||||
# files
|
# files
|
||||||
CROWSNEST_MULTI_CONFIG = CROWSNEST_DIR.joinpath("tools/.config")
|
CROWSNEST_MULTI_CONFIG = CROWSNEST_DIR.joinpath("tools/.config")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from subprocess import CalledProcessError, run
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from components.crowsnest import (
|
from components.crowsnest import (
|
||||||
|
CROWSNEST_BACKUP_DIR,
|
||||||
CROWSNEST_BIN_FILE,
|
CROWSNEST_BIN_FILE,
|
||||||
CROWSNEST_DIR,
|
CROWSNEST_DIR,
|
||||||
CROWSNEST_INSTALL_SCRIPT,
|
CROWSNEST_INSTALL_SCRIPT,
|
||||||
@@ -25,8 +26,8 @@ from components.crowsnest import (
|
|||||||
CROWSNEST_SERVICE_NAME,
|
CROWSNEST_SERVICE_NAME,
|
||||||
)
|
)
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.settings.kiauh_settings import KiauhSettings
|
from core.settings.kiauh_settings import KiauhSettings
|
||||||
from core.types.component_status import ComponentStatus
|
from core.types.component_status import ComponentStatus
|
||||||
from utils.common import (
|
from utils.common import (
|
||||||
@@ -126,11 +127,11 @@ def update_crowsnest() -> None:
|
|||||||
|
|
||||||
settings = KiauhSettings()
|
settings = KiauhSettings()
|
||||||
if settings.kiauh.backup_before_update:
|
if settings.kiauh.backup_before_update:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
svc.backup_directory(
|
bm.backup_directory(
|
||||||
source_path=CROWSNEST_DIR,
|
CROWSNEST_DIR.name,
|
||||||
target_path="crowsnest",
|
source=CROWSNEST_DIR,
|
||||||
backup_name="crowsnest",
|
target=CROWSNEST_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
|
|
||||||
git_pull_wrapper(CROWSNEST_DIR)
|
git_pull_wrapper(CROWSNEST_DIR)
|
||||||
|
|||||||
47
kiauh/components/droidklipp/droidklipp.py
Normal file
47
kiauh/components/droidklipp/droidklipp.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def install_droidklipp():
|
||||||
|
try:
|
||||||
|
print("Are you sure you want to install DroidKlipp? (Y/N)")
|
||||||
|
user_confirmation = input().strip().lower()
|
||||||
|
|
||||||
|
if user_confirmation != 'y':
|
||||||
|
print("DroidKlipp installation aborted.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Installing DroidKlipp...")
|
||||||
|
subprocess.run(['sudo', 'apt', 'install', '-y', 'adb', 'tmux'], check=True)
|
||||||
|
|
||||||
|
# Define the DroidKlipp repository URL and directory
|
||||||
|
droidklipp_repo_url = "https://github.com/CodeMasterCody3D/DroidKlipp.git"
|
||||||
|
droidklipp_dir = os.path.expanduser('~/DroidKlipp')
|
||||||
|
|
||||||
|
# Check if DroidKlipp directory exists, if not create it
|
||||||
|
if not os.path.isdir(droidklipp_dir):
|
||||||
|
print("DroidKlipp folder not found, creating directory...")
|
||||||
|
os.makedirs(droidklipp_dir)
|
||||||
|
|
||||||
|
# Clone the repository if not already cloned
|
||||||
|
if not os.path.isdir(os.path.join(droidklipp_dir, '.git')):
|
||||||
|
print("Cloning the DroidKlipp repository...")
|
||||||
|
subprocess.run(['git', 'clone', droidklipp_repo_url, droidklipp_dir], check=True)
|
||||||
|
else:
|
||||||
|
print("DroidKlipp repository already exists.")
|
||||||
|
|
||||||
|
# Change to the DroidKlipp directory
|
||||||
|
os.chdir(droidklipp_dir)
|
||||||
|
|
||||||
|
# Set executable permissions for the installation script
|
||||||
|
subprocess.run(['sudo', 'chmod', '+x', 'droidklipp.sh'], check=True)
|
||||||
|
|
||||||
|
# Run the installation script
|
||||||
|
subprocess.run(['./droidklipp.sh'], check=True)
|
||||||
|
|
||||||
|
print("DroidKlipp installation complete!")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error during installation: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Unexpected error: {e}")
|
||||||
|
|
||||||
|
# Ensure you call this with proper confirmation before installation
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
|
||||||
MODULE_PATH = Path(__file__).resolve().parent
|
MODULE_PATH = Path(__file__).resolve().parent
|
||||||
|
|
||||||
KLIPPER_REPO_URL = "https://github.com/Klipper3d/klipper.git"
|
KLIPPER_REPO_URL = "https://github.com/Klipper3d/klipper.git"
|
||||||
@@ -25,6 +27,7 @@ KLIPPER_SERVICE_NAME = "klipper.service"
|
|||||||
KLIPPER_DIR = Path.home().joinpath("klipper")
|
KLIPPER_DIR = Path.home().joinpath("klipper")
|
||||||
KLIPPER_KCONFIGS_DIR = Path.home().joinpath("klipper-kconfigs")
|
KLIPPER_KCONFIGS_DIR = Path.home().joinpath("klipper-kconfigs")
|
||||||
KLIPPER_ENV_DIR = Path.home().joinpath("klippy-env")
|
KLIPPER_ENV_DIR = Path.home().joinpath("klippy-env")
|
||||||
|
KLIPPER_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("klipper-backups")
|
||||||
|
|
||||||
# files
|
# files
|
||||||
KLIPPER_REQ_FILE = KLIPPER_DIR.joinpath("scripts/klippy-requirements.txt")
|
KLIPPER_REQ_FILE = KLIPPER_DIR.joinpath("scripts/klippy-requirements.txt")
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from subprocess import CalledProcessError, run
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
from components.klipper import (
|
from components.klipper import (
|
||||||
|
KLIPPER_BACKUP_DIR,
|
||||||
KLIPPER_DIR,
|
KLIPPER_DIR,
|
||||||
KLIPPER_ENV_DIR,
|
KLIPPER_ENV_DIR,
|
||||||
KLIPPER_INSTALL_SCRIPT,
|
KLIPPER_INSTALL_SCRIPT,
|
||||||
@@ -30,10 +31,10 @@ from components.webui_client.base_data import BaseWebClient
|
|||||||
from components.webui_client.client_config.client_config_setup import (
|
from components.webui_client.client_config.client_config_setup import (
|
||||||
create_client_config_symlink,
|
create_client_config_symlink,
|
||||||
)
|
)
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.constants import CURRENT_USER
|
from core.constants import CURRENT_USER
|
||||||
from core.instance_manager.base_instance import SUFFIX_BLACKLIST
|
from core.instance_manager.base_instance import SUFFIX_BLACKLIST
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
||||||
SimpleConfigParser,
|
SimpleConfigParser,
|
||||||
)
|
)
|
||||||
@@ -197,17 +198,9 @@ def create_example_printer_cfg(
|
|||||||
|
|
||||||
|
|
||||||
def backup_klipper_dir() -> None:
|
def backup_klipper_dir() -> None:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
svc.backup_directory(
|
bm.backup_directory("klipper", source=KLIPPER_DIR, target=KLIPPER_BACKUP_DIR)
|
||||||
source_path=KLIPPER_DIR,
|
bm.backup_directory("klippy-env", source=KLIPPER_ENV_DIR, target=KLIPPER_BACKUP_DIR)
|
||||||
backup_name="klipper",
|
|
||||||
target_path="klipper",
|
|
||||||
)
|
|
||||||
svc.backup_directory(
|
|
||||||
source_path=KLIPPER_ENV_DIR,
|
|
||||||
backup_name="klippy-env",
|
|
||||||
target_path="klipper",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def install_klipper_packages() -> None:
|
def install_klipper_packages() -> None:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
# ======================================================================= #
|
# ======================================================================= #
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
from core.constants import SYSTEMD
|
from core.constants import SYSTEMD
|
||||||
|
|
||||||
# repo
|
# repo
|
||||||
@@ -21,6 +22,7 @@ KLIPPERSCREEN_LOG_NAME = "KlipperScreen.log"
|
|||||||
# directories
|
# directories
|
||||||
KLIPPERSCREEN_DIR = Path.home().joinpath("KlipperScreen")
|
KLIPPERSCREEN_DIR = Path.home().joinpath("KlipperScreen")
|
||||||
KLIPPERSCREEN_ENV_DIR = Path.home().joinpath(".KlipperScreen-env")
|
KLIPPERSCREEN_ENV_DIR = Path.home().joinpath(".KlipperScreen-env")
|
||||||
|
KLIPPERSCREEN_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("klipperscreen-backups")
|
||||||
|
|
||||||
# files
|
# files
|
||||||
KLIPPERSCREEN_REQ_FILE = KLIPPERSCREEN_DIR.joinpath(
|
KLIPPERSCREEN_REQ_FILE = KLIPPERSCREEN_DIR.joinpath(
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from typing import List
|
|||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.klipperscreen import (
|
from components.klipperscreen import (
|
||||||
|
KLIPPERSCREEN_BACKUP_DIR,
|
||||||
KLIPPERSCREEN_DIR,
|
KLIPPERSCREEN_DIR,
|
||||||
KLIPPERSCREEN_ENV_DIR,
|
KLIPPERSCREEN_ENV_DIR,
|
||||||
KLIPPERSCREEN_INSTALL_SCRIPT,
|
KLIPPERSCREEN_INSTALL_SCRIPT,
|
||||||
@@ -24,10 +25,10 @@ from components.klipperscreen import (
|
|||||||
KLIPPERSCREEN_UPDATER_SECTION_NAME,
|
KLIPPERSCREEN_UPDATER_SECTION_NAME,
|
||||||
)
|
)
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.constants import SYSTEMD
|
from core.constants import SYSTEMD
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.settings.kiauh_settings import KiauhSettings
|
from core.settings.kiauh_settings import KiauhSettings
|
||||||
from core.types.component_status import ComponentStatus
|
from core.types.component_status import ComponentStatus
|
||||||
from utils.common import (
|
from utils.common import (
|
||||||
@@ -192,14 +193,14 @@ def remove_klipperscreen() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def backup_klipperscreen_dir() -> None:
|
def backup_klipperscreen_dir() -> None:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
svc.backup_directory(
|
bm.backup_directory(
|
||||||
source_path=KLIPPERSCREEN_DIR,
|
KLIPPERSCREEN_DIR.name,
|
||||||
backup_name="KlipperScreen",
|
source=KLIPPERSCREEN_DIR,
|
||||||
target_path="KlipperScreen",
|
target=KLIPPERSCREEN_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
svc.backup_directory(
|
bm.backup_directory(
|
||||||
source_path=KLIPPERSCREEN_ENV_DIR,
|
KLIPPERSCREEN_ENV_DIR.name,
|
||||||
backup_name="KlipperScreen-env",
|
source=KLIPPERSCREEN_ENV_DIR,
|
||||||
target_path="KlipperScreen",
|
target=KLIPPERSCREEN_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
|
||||||
MODULE_PATH = Path(__file__).resolve().parent
|
MODULE_PATH = Path(__file__).resolve().parent
|
||||||
|
|
||||||
MOONRAKER_REPO_URL = "https://github.com/Arksine/moonraker.git"
|
MOONRAKER_REPO_URL = "https://github.com/Arksine/moonraker.git"
|
||||||
@@ -23,6 +25,8 @@ MOONRAKER_ENV_FILE_NAME = "moonraker.env"
|
|||||||
# directories
|
# directories
|
||||||
MOONRAKER_DIR = Path.home().joinpath("moonraker")
|
MOONRAKER_DIR = Path.home().joinpath("moonraker")
|
||||||
MOONRAKER_ENV_DIR = Path.home().joinpath("moonraker-env")
|
MOONRAKER_ENV_DIR = Path.home().joinpath("moonraker-env")
|
||||||
|
MOONRAKER_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("moonraker-backups")
|
||||||
|
MOONRAKER_DB_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("moonraker-db-backups")
|
||||||
|
|
||||||
# files
|
# files
|
||||||
MOONRAKER_INSTALL_SCRIPT = MOONRAKER_DIR.joinpath("scripts/install-moonraker.sh")
|
MOONRAKER_INSTALL_SCRIPT = MOONRAKER_DIR.joinpath("scripts/install-moonraker.sh")
|
||||||
|
|||||||
@@ -61,9 +61,6 @@ class SysDepsParser:
|
|||||||
version = distro_info.get("distro_version")
|
version = distro_info.get("distro_version")
|
||||||
if version:
|
if version:
|
||||||
self.distro_version = _convert_version(version)
|
self.distro_version = _convert_version(version)
|
||||||
self.vendor: str = ""
|
|
||||||
if pathlib.Path("/etc/rpi-issue").is_file():
|
|
||||||
self.vendor = "raspberry-pi"
|
|
||||||
|
|
||||||
def _parse_spec(self, full_spec: str) -> str | None:
|
def _parse_spec(self, full_spec: str) -> str | None:
|
||||||
parts = full_spec.split(";", maxsplit=1)
|
parts = full_spec.split(";", maxsplit=1)
|
||||||
@@ -112,9 +109,6 @@ class SysDepsParser:
|
|||||||
elif req_var == "distro_id":
|
elif req_var == "distro_id":
|
||||||
left_op: str | Tuple[int | str, ...] = self.distro_id
|
left_op: str | Tuple[int | str, ...] = self.distro_id
|
||||||
right_op = dep_parts[2].strip().strip("\"'")
|
right_op = dep_parts[2].strip().strip("\"'")
|
||||||
elif req_var == "vendor":
|
|
||||||
left_op = self.vendor
|
|
||||||
right_op = dep_parts[2].strip().strip("\"'")
|
|
||||||
elif req_var == "distro_version":
|
elif req_var == "distro_version":
|
||||||
if not self.distro_version:
|
if not self.distro_version:
|
||||||
logging.info(
|
logging.info(
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ from typing import Dict, List, Optional
|
|||||||
|
|
||||||
from components.moonraker import (
|
from components.moonraker import (
|
||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
|
MOONRAKER_BACKUP_DIR,
|
||||||
|
MOONRAKER_DB_BACKUP_DIR,
|
||||||
MOONRAKER_DEFAULT_PORT,
|
MOONRAKER_DEFAULT_PORT,
|
||||||
MOONRAKER_DEPS_JSON_FILE,
|
MOONRAKER_DEPS_JSON_FILE,
|
||||||
MOONRAKER_DIR,
|
MOONRAKER_DIR,
|
||||||
@@ -23,8 +25,8 @@ from components.moonraker import (
|
|||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.moonraker.utils.sysdeps_parser import SysDepsParser
|
from components.moonraker.utils.sysdeps_parser import SysDepsParser
|
||||||
from components.webui_client.base_data import BaseWebClient
|
from components.webui_client.base_data import BaseWebClient
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
||||||
SimpleConfigParser,
|
SimpleConfigParser,
|
||||||
)
|
)
|
||||||
@@ -166,31 +168,21 @@ def create_example_moonraker_conf(
|
|||||||
|
|
||||||
|
|
||||||
def backup_moonraker_dir() -> None:
|
def backup_moonraker_dir() -> None:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
svc.backup_directory(
|
bm.backup_directory("moonraker", source=MOONRAKER_DIR, target=MOONRAKER_BACKUP_DIR)
|
||||||
source_path=MOONRAKER_DIR, backup_name="moonraker", target_path="moonraker"
|
bm.backup_directory(
|
||||||
)
|
"moonraker-env", source=MOONRAKER_ENV_DIR, target=MOONRAKER_BACKUP_DIR
|
||||||
svc.backup_directory(
|
|
||||||
source_path=MOONRAKER_ENV_DIR,
|
|
||||||
backup_name="moonraker-env",
|
|
||||||
target_path="moonraker",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def backup_moonraker_db_dir() -> None:
|
def backup_moonraker_db_dir() -> None:
|
||||||
instances: List[Moonraker] = get_instances(Moonraker)
|
instances: List[Moonraker] = get_instances(Moonraker)
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
|
|
||||||
if not instances:
|
|
||||||
Logger.print_info("Unable to find directory to backup!")
|
|
||||||
Logger.print_info("Are there no Moonraker instances installed?")
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
svc.backup_directory(
|
name = f"database-{instance.data_dir.name}"
|
||||||
source_path=instance.db_dir,
|
bm.backup_directory(
|
||||||
target_path=f"{instance.data_dir.name}",
|
name, source=instance.db_dir, target=MOONRAKER_DB_BACKUP_DIR
|
||||||
backup_name="database",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class BaseWebClient(ABC):
|
|||||||
display_name: str
|
display_name: str
|
||||||
client_dir: Path
|
client_dir: Path
|
||||||
config_file: Path
|
config_file: Path
|
||||||
|
backup_dir: Path
|
||||||
repo_path: str
|
repo_path: str
|
||||||
download_url: str
|
download_url: str
|
||||||
nginx_config: Path
|
nginx_config: Path
|
||||||
@@ -51,5 +52,6 @@ class BaseWebClientConfig(ABC):
|
|||||||
display_name: str
|
display_name: str
|
||||||
config_filename: str
|
config_filename: str
|
||||||
config_dir: Path
|
config_dir: Path
|
||||||
|
backup_dir: Path
|
||||||
repo_url: str
|
repo_url: str
|
||||||
config_section: str
|
config_section: str
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ from components.webui_client.base_data import (
|
|||||||
from components.webui_client.client_config.client_config_remove import (
|
from components.webui_client.client_config.client_config_remove import (
|
||||||
run_client_config_removal,
|
run_client_config_removal,
|
||||||
)
|
)
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.constants import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
from core.constants import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.services.message_service import Message
|
from core.services.message_service import Message
|
||||||
from core.types.color import Color
|
from core.types.color import Color
|
||||||
from utils.config_utils import remove_config_section
|
from utils.config_utils import remove_config_section
|
||||||
@@ -43,19 +43,8 @@ def run_client_removal(
|
|||||||
kl_instances: List[Klipper] = get_instances(Klipper)
|
kl_instances: List[Klipper] = get_instances(Klipper)
|
||||||
|
|
||||||
if backup_config:
|
if backup_config:
|
||||||
version = ""
|
bm = BackupManager()
|
||||||
src = client.client_dir
|
if bm.backup_file(client.config_file):
|
||||||
if src.joinpath(".version").exists():
|
|
||||||
with open(src.joinpath(".version"), "r") as v:
|
|
||||||
version = v.readlines()[0]
|
|
||||||
|
|
||||||
svc = BackupService()
|
|
||||||
target_path = svc.backup_root.joinpath(f"{client.client_dir.name}_{version}")
|
|
||||||
success = svc.backup_file(
|
|
||||||
source_path=client.config_file,
|
|
||||||
target_path=target_path,
|
|
||||||
)
|
|
||||||
if success:
|
|
||||||
completion_msg.text.append(f"● {client.config_file.name} backup created")
|
completion_msg.text.append(f"● {client.config_file.name} backup created")
|
||||||
|
|
||||||
if remove_client:
|
if remove_client:
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ from components.webui_client.base_data import (
|
|||||||
from components.webui_client.client_dialogs import print_client_port_select_dialog
|
from components.webui_client.client_dialogs import print_client_port_select_dialog
|
||||||
from components.webui_client.fluidd_data import FluiddData
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
from components.webui_client.mainsail_data import MainsailData
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.constants import (
|
from core.constants import (
|
||||||
NGINX_CONFD,
|
NGINX_CONFD,
|
||||||
NGINX_SITES_AVAILABLE,
|
NGINX_SITES_AVAILABLE,
|
||||||
NGINX_SITES_ENABLED,
|
NGINX_SITES_ENABLED,
|
||||||
)
|
)
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.settings.kiauh_settings import KiauhSettings, WebUiSettings
|
from core.settings.kiauh_settings import KiauhSettings, WebUiSettings
|
||||||
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
||||||
SimpleConfigParser,
|
SimpleConfigParser,
|
||||||
@@ -175,39 +175,26 @@ def get_remote_client_version(client: BaseWebClient) -> str | None:
|
|||||||
|
|
||||||
|
|
||||||
def backup_client_data(client: BaseWebClient) -> None:
|
def backup_client_data(client: BaseWebClient) -> None:
|
||||||
version = ""
|
name = client.name
|
||||||
src = client.client_dir
|
src = client.client_dir
|
||||||
if src.joinpath(".version").exists():
|
dest = client.backup_dir
|
||||||
|
|
||||||
with open(src.joinpath(".version"), "r") as v:
|
with open(src.joinpath(".version"), "r") as v:
|
||||||
version = v.readlines()[0]
|
version = v.readlines()[0]
|
||||||
|
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
target_path = svc.backup_root.joinpath(f"{client.client_dir.name}_{version}")
|
bm.backup_directory(f"{name}-{version}", src, dest)
|
||||||
svc.backup_directory(
|
bm.backup_file(client.config_file, dest)
|
||||||
source_path=client.client_dir,
|
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath(name), dest)
|
||||||
target_path=target_path,
|
|
||||||
backup_name=client.name,
|
|
||||||
)
|
|
||||||
svc.backup_file(
|
|
||||||
source_path=client.config_file,
|
|
||||||
target_path=target_path,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def backup_client_config_data(client: BaseWebClient) -> None:
|
def backup_client_config_data(client: BaseWebClient) -> None:
|
||||||
version = ""
|
client_config = client.client_config
|
||||||
src = client.client_dir
|
name = client_config.name
|
||||||
if src.joinpath(".version").exists():
|
source = client_config.config_dir
|
||||||
with open(src.joinpath(".version"), "r") as v:
|
target = client_config.backup_dir
|
||||||
version = v.readlines()[0]
|
bm = BackupManager()
|
||||||
|
bm.backup_directory(name, source, target)
|
||||||
svc = BackupService()
|
|
||||||
target_path = svc.backup_root.joinpath(f"{client.client_dir.name}_{version}")
|
|
||||||
svc.backup_directory(
|
|
||||||
source_path=client.client_config.config_dir,
|
|
||||||
target_path=target_path,
|
|
||||||
backup_name=client.client_config.name,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_existing_clients() -> List[BaseWebClient]:
|
def get_existing_clients() -> List[BaseWebClient]:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from components.webui_client.base_data import (
|
|||||||
WebClientConfigType,
|
WebClientConfigType,
|
||||||
WebClientType,
|
WebClientType,
|
||||||
)
|
)
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
from core.constants import NGINX_SITES_AVAILABLE
|
from core.constants import NGINX_SITES_AVAILABLE
|
||||||
|
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ class FluiddConfigWeb(BaseWebClientConfig):
|
|||||||
config_dir: Path = Path.home().joinpath("fluidd-config")
|
config_dir: Path = Path.home().joinpath("fluidd-config")
|
||||||
config_filename: str = "fluidd.cfg"
|
config_filename: str = "fluidd.cfg"
|
||||||
config_section: str = f"include {config_filename}"
|
config_section: str = f"include {config_filename}"
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("fluidd-config-backups")
|
||||||
repo_url: str = "https://github.com/fluidd-core/fluidd-config.git"
|
repo_url: str = "https://github.com/fluidd-core/fluidd-config.git"
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +43,7 @@ class FluiddData(BaseWebClient):
|
|||||||
display_name: str = name.capitalize()
|
display_name: str = name.capitalize()
|
||||||
client_dir: Path = Path.home().joinpath("fluidd")
|
client_dir: Path = Path.home().joinpath("fluidd")
|
||||||
config_file: Path = client_dir.joinpath("config.json")
|
config_file: Path = client_dir.joinpath("config.json")
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("fluidd-backups")
|
||||||
repo_path: str = "fluidd-core/fluidd"
|
repo_path: str = "fluidd-core/fluidd"
|
||||||
nginx_config: Path = NGINX_SITES_AVAILABLE.joinpath("fluidd")
|
nginx_config: Path = NGINX_SITES_AVAILABLE.joinpath("fluidd")
|
||||||
nginx_access_log: Path = Path("/var/log/nginx/fluidd-access.log")
|
nginx_access_log: Path = Path("/var/log/nginx/fluidd-access.log")
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from components.webui_client.base_data import (
|
|||||||
WebClientConfigType,
|
WebClientConfigType,
|
||||||
WebClientType,
|
WebClientType,
|
||||||
)
|
)
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
from core.constants import NGINX_SITES_AVAILABLE
|
from core.constants import NGINX_SITES_AVAILABLE
|
||||||
|
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ class MainsailConfigWeb(BaseWebClientConfig):
|
|||||||
config_dir: Path = Path.home().joinpath("mainsail-config")
|
config_dir: Path = Path.home().joinpath("mainsail-config")
|
||||||
config_filename: str = "mainsail.cfg"
|
config_filename: str = "mainsail.cfg"
|
||||||
config_section: str = f"include {config_filename}"
|
config_section: str = f"include {config_filename}"
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("mainsail-config-backups")
|
||||||
repo_url: str = "https://github.com/mainsail-crew/mainsail-config.git"
|
repo_url: str = "https://github.com/mainsail-crew/mainsail-config.git"
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +43,7 @@ class MainsailData(BaseWebClient):
|
|||||||
display_name: str = name.capitalize()
|
display_name: str = name.capitalize()
|
||||||
client_dir: Path = Path.home().joinpath("mainsail")
|
client_dir: Path = Path.home().joinpath("mainsail")
|
||||||
config_file: Path = client_dir.joinpath("config.json")
|
config_file: Path = client_dir.joinpath("config.json")
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("mainsail-backups")
|
||||||
repo_path: str = "mainsail-crew/mainsail"
|
repo_path: str = "mainsail-crew/mainsail"
|
||||||
nginx_config: Path = NGINX_SITES_AVAILABLE.joinpath("mainsail")
|
nginx_config: Path = NGINX_SITES_AVAILABLE.joinpath("mainsail")
|
||||||
nginx_access_log: Path = Path("/var/log/nginx/mainsail-access.log")
|
nginx_access_log: Path = Path("/var/log/nginx/mainsail-access.log")
|
||||||
|
|||||||
12
kiauh/core/backup_manager/__init__.py
Normal file
12
kiauh/core/backup_manager/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2025 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# This file is part of KIAUH - Klipper Installation And Update Helper #
|
||||||
|
# https://github.com/dw-0/kiauh #
|
||||||
|
# #
|
||||||
|
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||||
|
# ======================================================================= #
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
BACKUP_ROOT_DIR = Path.home().joinpath("kiauh-backups")
|
||||||
108
kiauh/core/backup_manager/backup_manager.py
Normal file
108
kiauh/core/backup_manager/backup_manager.py
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2025 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# This file is part of KIAUH - Klipper Installation And Update Helper #
|
||||||
|
# https://github.com/dw-0/kiauh #
|
||||||
|
# #
|
||||||
|
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||||
|
# ======================================================================= #
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
from core.logger import Logger
|
||||||
|
from utils.common import get_current_date
|
||||||
|
|
||||||
|
|
||||||
|
class BackupManagerException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
# noinspection PyMethodMayBeStatic
|
||||||
|
class BackupManager:
|
||||||
|
def __init__(self, backup_root_dir: Path = BACKUP_ROOT_DIR):
|
||||||
|
self._backup_root_dir: Path = backup_root_dir
|
||||||
|
self._ignore_folders: List[str] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def backup_root_dir(self) -> Path:
|
||||||
|
return self._backup_root_dir
|
||||||
|
|
||||||
|
@backup_root_dir.setter
|
||||||
|
def backup_root_dir(self, value: Path):
|
||||||
|
self._backup_root_dir = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ignore_folders(self) -> List[str]:
|
||||||
|
return self._ignore_folders
|
||||||
|
|
||||||
|
@ignore_folders.setter
|
||||||
|
def ignore_folders(self, value: List[str]):
|
||||||
|
self._ignore_folders = value
|
||||||
|
|
||||||
|
def backup_file(
|
||||||
|
self, file: Path, target: Path | None = None, custom_filename=None
|
||||||
|
) -> bool:
|
||||||
|
Logger.print_status(f"Creating backup of {file} ...")
|
||||||
|
|
||||||
|
if not file.exists():
|
||||||
|
Logger.print_info("File does not exist! Skipping ...")
|
||||||
|
return False
|
||||||
|
|
||||||
|
target = self.backup_root_dir if target is None else target
|
||||||
|
|
||||||
|
if Path(file).is_file():
|
||||||
|
date = get_current_date().get("date")
|
||||||
|
time = get_current_date().get("time")
|
||||||
|
filename = f"{file.stem}-{date}-{time}{file.suffix}"
|
||||||
|
filename = custom_filename if custom_filename is not None else filename
|
||||||
|
try:
|
||||||
|
Path(target).mkdir(exist_ok=True)
|
||||||
|
shutil.copyfile(file, target.joinpath(filename))
|
||||||
|
Logger.print_ok("Backup successful!")
|
||||||
|
return True
|
||||||
|
except OSError as e:
|
||||||
|
Logger.print_error(f"Unable to backup '{file}':\n{e}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
Logger.print_info(f"File '{file}' not found ...")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def backup_directory(
|
||||||
|
self, name: str, source: Path, target: Path | None = None
|
||||||
|
) -> Path | None:
|
||||||
|
Logger.print_status(f"Creating backup of {name} in {target} ...")
|
||||||
|
|
||||||
|
if source is None or not Path(source).exists():
|
||||||
|
Logger.print_info("Source directory does not exist! Skipping ...")
|
||||||
|
return None
|
||||||
|
|
||||||
|
target = self.backup_root_dir if target is None else target
|
||||||
|
try:
|
||||||
|
date = get_current_date().get("date")
|
||||||
|
time = get_current_date().get("time")
|
||||||
|
backup_target = target.joinpath(f"{name.lower()}-{date}-{time}")
|
||||||
|
shutil.copytree(
|
||||||
|
source,
|
||||||
|
backup_target,
|
||||||
|
ignore=self.ignore_folders_func,
|
||||||
|
ignore_dangling_symlinks=True,
|
||||||
|
)
|
||||||
|
Logger.print_ok("Backup successful!")
|
||||||
|
|
||||||
|
return backup_target
|
||||||
|
|
||||||
|
except OSError as e:
|
||||||
|
Logger.print_error(f"Unable to backup directory '{source}':\n{e}")
|
||||||
|
raise BackupManagerException(f"Unable to backup directory '{source}':\n{e}")
|
||||||
|
|
||||||
|
def ignore_folders_func(self, dirpath, filenames) -> List[str]:
|
||||||
|
return (
|
||||||
|
[f for f in filenames if f in self._ignore_folders]
|
||||||
|
if self._ignore_folders
|
||||||
|
else []
|
||||||
|
)
|
||||||
@@ -11,6 +11,8 @@ import os
|
|||||||
import pwd
|
import pwd
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
|
||||||
# global dependencies
|
# global dependencies
|
||||||
GLOBAL_DEPS = ["git", "wget", "curl", "unzip", "dfu-util", "python3-virtualenv"]
|
GLOBAL_DEPS = ["git", "wget", "curl", "unzip", "dfu-util", "python3-virtualenv"]
|
||||||
|
|
||||||
@@ -22,6 +24,7 @@ CURRENT_USER = pwd.getpwuid(os.getuid())[0]
|
|||||||
|
|
||||||
# dirs
|
# dirs
|
||||||
SYSTEMD = Path("/etc/systemd/system")
|
SYSTEMD = Path("/etc/systemd/system")
|
||||||
|
PRINTER_DATA_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("printer-data-backups")
|
||||||
NGINX_SITES_AVAILABLE = Path("/etc/nginx/sites-available")
|
NGINX_SITES_AVAILABLE = Path("/etc/nginx/sites-available")
|
||||||
NGINX_SITES_ENABLED = Path("/etc/nginx/sites-enabled")
|
NGINX_SITES_ENABLED = Path("/etc/nginx/sites-enabled")
|
||||||
NGINX_CONFD = Path("/etc/nginx/conf.d")
|
NGINX_CONFD = Path("/etc/nginx/conf.d")
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|||||||
import textwrap
|
import textwrap
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
|
from components.droidklipp.droidklipp import install_droidklipp
|
||||||
from components.crowsnest.crowsnest import install_crowsnest
|
from components.crowsnest.crowsnest import install_crowsnest
|
||||||
from components.klipper.services.klipper_setup_service import KlipperSetupService
|
from components.klipper.services.klipper_setup_service import KlipperSetupService
|
||||||
from components.klipperscreen.klipperscreen import install_klipperscreen
|
from components.klipperscreen.klipperscreen import install_klipperscreen
|
||||||
@@ -41,7 +42,6 @@ class InstallMenu(BaseMenu):
|
|||||||
|
|
||||||
def set_previous_menu(self, previous_menu: Type[BaseMenu] | None) -> None:
|
def set_previous_menu(self, previous_menu: Type[BaseMenu] | None) -> None:
|
||||||
from core.menus.main_menu import MainMenu
|
from core.menus.main_menu import MainMenu
|
||||||
|
|
||||||
self.previous_menu = previous_menu if previous_menu is not None else MainMenu
|
self.previous_menu = previous_menu if previous_menu is not None else MainMenu
|
||||||
|
|
||||||
def set_options(self) -> None:
|
def set_options(self) -> None:
|
||||||
@@ -53,7 +53,9 @@ class InstallMenu(BaseMenu):
|
|||||||
"5": Option(method=self.install_mainsail_config),
|
"5": Option(method=self.install_mainsail_config),
|
||||||
"6": Option(method=self.install_fluidd_config),
|
"6": Option(method=self.install_fluidd_config),
|
||||||
"7": Option(method=self.install_klipperscreen),
|
"7": Option(method=self.install_klipperscreen),
|
||||||
"8": Option(method=self.install_crowsnest),
|
"8": Option(method=self.install_droidklipp), # Add DroidKlipp option
|
||||||
|
"9": Option(method=self.install_crowsnest),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def print_menu(self) -> None:
|
def print_menu(self) -> None:
|
||||||
@@ -62,15 +64,17 @@ class InstallMenu(BaseMenu):
|
|||||||
╟───────────────────────────┬───────────────────────────╢
|
╟───────────────────────────┬───────────────────────────╢
|
||||||
║ Firmware & API: │ Touchscreen GUI: ║
|
║ Firmware & API: │ Touchscreen GUI: ║
|
||||||
║ 1) [Klipper] │ 7) [KlipperScreen] ║
|
║ 1) [Klipper] │ 7) [KlipperScreen] ║
|
||||||
║ 2) [Moonraker] │ ║
|
║ 2) [Moonraker] │ 8) [DroidKlipp] ║
|
||||||
|
║ │ ║
|
||||||
║ │ Webcam Streamer: ║
|
║ │ Webcam Streamer: ║
|
||||||
║ Webinterface: │ 8) [Crowsnest] ║
|
║ Webinterface: │ 9) [Crowsnest] ║
|
||||||
║ 3) [Mainsail] │ ║
|
║ 3) [Mainsail] │ ║
|
||||||
║ 4) [Fluidd] │ ║
|
║ 4) [Fluidd] │ ║
|
||||||
║ │ ║
|
║ │ ║
|
||||||
║ Client-Config: │ ║
|
║ Client-Config: │ ║
|
||||||
║ 5) [Mainsail-Config] │ ║
|
║ 5) [Mainsail-Config] │ ║
|
||||||
║ 6) [Fluidd-Config] │ ║
|
║ 6) [Fluidd-Config] │ ║
|
||||||
|
║ │ ║
|
||||||
╟───────────────────────────┴───────────────────────────╢
|
╟───────────────────────────┴───────────────────────────╢
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
@@ -107,3 +111,6 @@ class InstallMenu(BaseMenu):
|
|||||||
|
|
||||||
def install_crowsnest(self, **kwargs) -> None:
|
def install_crowsnest(self, **kwargs) -> None:
|
||||||
install_crowsnest()
|
install_crowsnest()
|
||||||
|
|
||||||
|
def install_droidklipp(self, **kwargs) -> None:
|
||||||
|
install_droidklipp()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import sys
|
|||||||
import textwrap
|
import textwrap
|
||||||
from typing import Callable, Type
|
from typing import Callable, Type
|
||||||
|
|
||||||
|
from components.droidklipp.droidklipp import install_droidklipp
|
||||||
from components.crowsnest.crowsnest import get_crowsnest_status
|
from components.crowsnest.crowsnest import get_crowsnest_status
|
||||||
from components.klipper.klipper_utils import get_klipper_status
|
from components.klipper.klipper_utils import get_klipper_status
|
||||||
from components.klipperscreen.klipperscreen import get_klipperscreen_status
|
from components.klipperscreen.klipperscreen import get_klipperscreen_status
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2025 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# This file is part of KIAUH - Klipper Installation And Update Helper #
|
|
||||||
# https://github.com/dw-0/kiauh #
|
|
||||||
# #
|
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
|
||||||
# ======================================================================= #
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import shutil
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from core.logger import Logger
|
|
||||||
|
|
||||||
|
|
||||||
class BackupService:
|
|
||||||
def __init__(self):
|
|
||||||
self._backup_root = Path.home().joinpath("kiauh_backups")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def backup_root(self) -> Path:
|
|
||||||
return self._backup_root
|
|
||||||
|
|
||||||
def backup_file(
|
|
||||||
self,
|
|
||||||
source_path: Path,
|
|
||||||
target_path: Optional[Path | str] = None,
|
|
||||||
target_name: Optional[str] = None,
|
|
||||||
) -> bool:
|
|
||||||
source_path = Path(source_path)
|
|
||||||
|
|
||||||
Logger.print_status(f"Creating backup of {source_path} ...")
|
|
||||||
|
|
||||||
if not source_path.exists():
|
|
||||||
Logger.print_info(
|
|
||||||
f"File '{source_path}' does not exist! Skipping backup..."
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not source_path.is_file():
|
|
||||||
Logger.print_info(f"'{source_path}' is not a file! Skipping backup...")
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._backup_root.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
||||||
filename = (
|
|
||||||
target_name or f"{source_path.stem}_{timestamp}{source_path.suffix}"
|
|
||||||
)
|
|
||||||
if target_path is not None:
|
|
||||||
backup_path = self._backup_root.joinpath(target_path, filename)
|
|
||||||
else:
|
|
||||||
backup_path = self._backup_root.joinpath(filename)
|
|
||||||
|
|
||||||
backup_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
shutil.copy2(source_path, backup_path)
|
|
||||||
|
|
||||||
Logger.print_ok(
|
|
||||||
f"Successfully backed up '{source_path}' to '{backup_path}'"
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
Logger.print_error(f"Failed to backup '{source_path}': {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def backup_directory(
|
|
||||||
self,
|
|
||||||
source_path: Path,
|
|
||||||
backup_name: str,
|
|
||||||
target_path: Optional[Path | str] = None,
|
|
||||||
) -> Optional[Path]:
|
|
||||||
source_path = Path(source_path)
|
|
||||||
|
|
||||||
Logger.print_status(f"Creating backup of {source_path} ...")
|
|
||||||
|
|
||||||
if not source_path.exists():
|
|
||||||
Logger.print_info(
|
|
||||||
f"Directory '{source_path}' does not exist! Skipping backup..."
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not source_path.is_dir():
|
|
||||||
Logger.print_info(f"'{source_path}' is not a directory! Skipping backup...")
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._backup_root.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
||||||
backup_dir_name = f"{backup_name}_{timestamp}"
|
|
||||||
|
|
||||||
if target_path is not None:
|
|
||||||
backup_path = self._backup_root.joinpath(target_path, backup_dir_name)
|
|
||||||
else:
|
|
||||||
backup_path = self._backup_root.joinpath(backup_dir_name)
|
|
||||||
|
|
||||||
shutil.copytree(source_path, backup_path)
|
|
||||||
|
|
||||||
Logger.print_ok(
|
|
||||||
f"Successfully backed up '{source_path}' to '{backup_path}'"
|
|
||||||
)
|
|
||||||
return backup_path
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
Logger.print_error(f"Failed to backup directory '{source_path}': {e}")
|
|
||||||
return None
|
|
||||||
@@ -14,8 +14,8 @@ from typing import Any, Callable, List, TypeVar
|
|||||||
|
|
||||||
from components.klipper import KLIPPER_REPO_URL
|
from components.klipper import KLIPPER_REPO_URL
|
||||||
from components.moonraker import MOONRAKER_REPO_URL
|
from components.moonraker import MOONRAKER_REPO_URL
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
||||||
SimpleConfigParser,
|
SimpleConfigParser,
|
||||||
)
|
)
|
||||||
@@ -374,8 +374,8 @@ class KiauhSettings:
|
|||||||
kill()
|
kill()
|
||||||
|
|
||||||
def _migrate_repo_config(self) -> None:
|
def _migrate_repo_config(self) -> None:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
if not svc.backup_file(CUSTOM_CFG):
|
if not bm.backup_file(CUSTOM_CFG):
|
||||||
Logger.print_dialog(
|
Logger.print_dialog(
|
||||||
DialogType.ERROR,
|
DialogType.ERROR,
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -9,13 +9,12 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import datetime
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
||||||
SimpleConfigParser,
|
SimpleConfigParser,
|
||||||
)
|
)
|
||||||
@@ -110,13 +109,11 @@ class GcodeShellCmdExtension(BaseExtension):
|
|||||||
Logger.warn(f"Unable to create example config: {e}")
|
Logger.warn(f"Unable to create example config: {e}")
|
||||||
|
|
||||||
# backup each printer.cfg before modification
|
# backup each printer.cfg before modification
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
svc.backup_file(
|
bm.backup_file(
|
||||||
source_path=instance.cfg_file,
|
instance.cfg_file,
|
||||||
target_path=f"{instance.data_dir.name}/config_{timestamp}",
|
custom_filename=f"{instance.suffix}.printer.cfg",
|
||||||
target_name=instance.cfg_file.name,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# add section to printer.cfg if not already defined
|
# add section to printer.cfg if not already defined
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
from core.constants import SYSTEMD
|
from core.constants import SYSTEMD
|
||||||
|
|
||||||
# repo
|
# repo
|
||||||
@@ -22,6 +23,7 @@ MOBILERAKER_LOG_NAME = "mobileraker.log"
|
|||||||
# directories
|
# directories
|
||||||
MOBILERAKER_DIR = Path.home().joinpath("mobileraker_companion")
|
MOBILERAKER_DIR = Path.home().joinpath("mobileraker_companion")
|
||||||
MOBILERAKER_ENV_DIR = Path.home().joinpath("mobileraker-env")
|
MOBILERAKER_ENV_DIR = Path.home().joinpath("mobileraker-env")
|
||||||
|
MOBILERAKER_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("mobileraker-backups")
|
||||||
|
|
||||||
# files
|
# files
|
||||||
MOBILERAKER_INSTALL_SCRIPT = MOBILERAKER_DIR.joinpath("scripts/install.sh")
|
MOBILERAKER_INSTALL_SCRIPT = MOBILERAKER_DIR.joinpath("scripts/install.sh")
|
||||||
|
|||||||
@@ -13,12 +13,13 @@ from typing import List
|
|||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.settings.kiauh_settings import KiauhSettings
|
from core.settings.kiauh_settings import KiauhSettings
|
||||||
from extensions.base_extension import BaseExtension
|
from extensions.base_extension import BaseExtension
|
||||||
from extensions.mobileraker import (
|
from extensions.mobileraker import (
|
||||||
|
MOBILERAKER_BACKUP_DIR,
|
||||||
MOBILERAKER_DIR,
|
MOBILERAKER_DIR,
|
||||||
MOBILERAKER_ENV_DIR,
|
MOBILERAKER_ENV_DIR,
|
||||||
MOBILERAKER_INSTALL_SCRIPT,
|
MOBILERAKER_INSTALL_SCRIPT,
|
||||||
@@ -178,14 +179,14 @@ class MobilerakerExtension(BaseExtension):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _backup_mobileraker_dir(self) -> None:
|
def _backup_mobileraker_dir(self) -> None:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
svc.backup_directory(
|
bm.backup_directory(
|
||||||
source_path=MOBILERAKER_DIR,
|
MOBILERAKER_DIR.name,
|
||||||
backup_name="mobileraker",
|
source=MOBILERAKER_DIR,
|
||||||
target_path="mobileraker",
|
target=MOBILERAKER_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
svc.backup_directory(
|
bm.backup_directory(
|
||||||
source_path=MOBILERAKER_ENV_DIR,
|
MOBILERAKER_ENV_DIR.name,
|
||||||
backup_name="mobileraker-env",
|
source=MOBILERAKER_ENV_DIR,
|
||||||
target_path="mobileraker",
|
target=MOBILERAKER_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ from components.moonraker.moonraker import Moonraker
|
|||||||
from components.moonraker.services.moonraker_instance_service import (
|
from components.moonraker.services.moonraker_instance_service import (
|
||||||
MoonrakerInstanceService,
|
MoonrakerInstanceService,
|
||||||
)
|
)
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from extensions.base_extension import BaseExtension
|
from extensions.base_extension import BaseExtension
|
||||||
from extensions.spoolman import (
|
from extensions.spoolman import (
|
||||||
SPOOLMAN_COMPOSE_FILE,
|
SPOOLMAN_COMPOSE_FILE,
|
||||||
@@ -123,15 +123,16 @@ class SpoolmanExtension(BaseExtension):
|
|||||||
"Failed to remove Spoolman image! Please remove it manually."
|
"Failed to remove Spoolman image! Please remove it manually."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# backup Spoolman directory to ~/spoolman_data-<timestamp> before removing it
|
||||||
try:
|
try:
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
success = svc.backup_directory(
|
result = bm.backup_directory(
|
||||||
source_path=SPOOLMAN_DIR,
|
f"{SPOOLMAN_DIR.name}_data",
|
||||||
backup_name="spoolman",
|
source=SPOOLMAN_DIR,
|
||||||
target_path="spoolman",
|
target=SPOOLMAN_DIR.parent,
|
||||||
)
|
)
|
||||||
if success:
|
if result:
|
||||||
Logger.print_ok(f"Spoolman data backed up to {success}")
|
Logger.print_ok(f"Spoolman data backed up to {result}")
|
||||||
Logger.print_status("Removing Spoolman directory...")
|
Logger.print_status("Removing Spoolman directory...")
|
||||||
if run_remove_routines(SPOOLMAN_DIR):
|
if run_remove_routines(SPOOLMAN_DIR):
|
||||||
Logger.print_ok("Spoolman directory removed!")
|
Logger.print_ok("Spoolman directory removed!")
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from pathlib import Path
|
|||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from components.klipper import (
|
from components.klipper import (
|
||||||
|
KLIPPER_BACKUP_DIR,
|
||||||
KLIPPER_DIR,
|
KLIPPER_DIR,
|
||||||
KLIPPER_ENV_DIR,
|
KLIPPER_ENV_DIR,
|
||||||
KLIPPER_REQ_FILE,
|
KLIPPER_REQ_FILE,
|
||||||
@@ -20,6 +21,7 @@ from components.klipper import (
|
|||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.klipper.klipper_utils import install_klipper_packages
|
from components.klipper.klipper_utils import install_klipper_packages
|
||||||
from components.moonraker import (
|
from components.moonraker import (
|
||||||
|
MOONRAKER_BACKUP_DIR,
|
||||||
MOONRAKER_DIR,
|
MOONRAKER_DIR,
|
||||||
MOONRAKER_ENV_DIR,
|
MOONRAKER_ENV_DIR,
|
||||||
MOONRAKER_REQ_FILE,
|
MOONRAKER_REQ_FILE,
|
||||||
@@ -28,10 +30,10 @@ from components.moonraker.moonraker import Moonraker
|
|||||||
from components.moonraker.services.moonraker_setup_service import (
|
from components.moonraker.services.moonraker_setup_service import (
|
||||||
install_moonraker_packages,
|
install_moonraker_packages,
|
||||||
)
|
)
|
||||||
|
from core.backup_manager.backup_manager import BackupManager, BackupManagerException
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from core.services.backup_service import BackupService
|
from utils.git_utils import GitException, get_repo_name, git_clone_wrapper
|
||||||
from utils.git_utils import GitException, git_clone_wrapper
|
|
||||||
from utils.instance_utils import get_instances
|
from utils.instance_utils import get_instances
|
||||||
from utils.sys_utils import (
|
from utils.sys_utils import (
|
||||||
VenvCreationFailedException,
|
VenvCreationFailedException,
|
||||||
@@ -50,6 +52,7 @@ def run_switch_repo_routine(
|
|||||||
repo_dir: Path = KLIPPER_DIR if name == "klipper" else MOONRAKER_DIR
|
repo_dir: Path = KLIPPER_DIR if name == "klipper" else MOONRAKER_DIR
|
||||||
env_dir: Path = KLIPPER_ENV_DIR if name == "klipper" else MOONRAKER_ENV_DIR
|
env_dir: Path = KLIPPER_ENV_DIR if name == "klipper" else MOONRAKER_ENV_DIR
|
||||||
req_file = KLIPPER_REQ_FILE if name == "klipper" else MOONRAKER_REQ_FILE
|
req_file = KLIPPER_REQ_FILE if name == "klipper" else MOONRAKER_REQ_FILE
|
||||||
|
backup_dir: Path = KLIPPER_BACKUP_DIR if name == "klipper" else MOONRAKER_BACKUP_DIR
|
||||||
_type = Klipper if name == "klipper" else Moonraker
|
_type = Klipper if name == "klipper" else Moonraker
|
||||||
|
|
||||||
# step 1: stop all instances
|
# step 1: stop all instances
|
||||||
@@ -61,17 +64,19 @@ def run_switch_repo_routine(
|
|||||||
env_dir_backup_path: Path | None = None
|
env_dir_backup_path: Path | None = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
svc = BackupService()
|
# step 2: backup old repo and env
|
||||||
svc.backup_directory(
|
org, _ = get_repo_name(repo_dir)
|
||||||
source_path=repo_dir,
|
backup_dir = backup_dir.joinpath(org)
|
||||||
backup_name=name,
|
bm = BackupManager()
|
||||||
target_path=name,
|
repo_dir_backup_path = bm.backup_directory(
|
||||||
|
repo_dir.name,
|
||||||
|
repo_dir,
|
||||||
|
backup_dir,
|
||||||
)
|
)
|
||||||
env_backup_name: str = f"{name if name == 'moonraker' else 'klippy'}-env"
|
env_dir_backup_path = bm.backup_directory(
|
||||||
svc.backup_directory(
|
env_dir.name,
|
||||||
source_path=env_dir,
|
env_dir,
|
||||||
backup_name=env_backup_name,
|
backup_dir,
|
||||||
target_path=name,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not (repo_url or branch):
|
if not (repo_url or branch):
|
||||||
@@ -96,6 +101,10 @@ def run_switch_repo_routine(
|
|||||||
|
|
||||||
Logger.print_ok(f"Switched to {repo_url} at branch {branch}!")
|
Logger.print_ok(f"Switched to {repo_url} at branch {branch}!")
|
||||||
|
|
||||||
|
except BackupManagerException as e:
|
||||||
|
Logger.print_error(f"Error during backup of repository: {e}")
|
||||||
|
raise RepoSwitchFailedException(e)
|
||||||
|
|
||||||
except (GitException, VenvCreationFailedException) as e:
|
except (GitException, VenvCreationFailedException) as e:
|
||||||
# if something goes wrong during cloning or recreating the virtualenv,
|
# if something goes wrong during cloning or recreating the virtualenv,
|
||||||
# we restore the backup of the repo and env
|
# we restore the backup of the repo and env
|
||||||
@@ -113,9 +122,6 @@ def run_switch_repo_routine(
|
|||||||
Logger.print_error(f"Something went wrong: {e}")
|
Logger.print_error(f"Something went wrong: {e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
raise RepoSwitchFailedException(e)
|
|
||||||
|
|
||||||
Logger.print_status(f"Restarting all {_type.__name__} instances ...")
|
Logger.print_status(f"Restarting all {_type.__name__} instances ...")
|
||||||
InstanceManager.start_all(instances)
|
InstanceManager.start_all(instances)
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from components.droidklipp.droidklipp import install_droidklipp
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -18,9 +20,9 @@ from components.klipper.klipper import Klipper
|
|||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from core.constants import (
|
from core.constants import (
|
||||||
GLOBAL_DEPS,
|
GLOBAL_DEPS,
|
||||||
|
PRINTER_DATA_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from core.services.backup_service import BackupService
|
|
||||||
from core.types.color import Color
|
from core.types.color import Color
|
||||||
from core.types.component_status import ComponentStatus, StatusCode
|
from core.types.component_status import ComponentStatus, StatusCode
|
||||||
from utils.git_utils import (
|
from utils.git_utils import (
|
||||||
@@ -152,8 +154,11 @@ def get_install_status(
|
|||||||
|
|
||||||
|
|
||||||
def backup_printer_config_dir() -> None:
|
def backup_printer_config_dir() -> None:
|
||||||
|
# local import to prevent circular import
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
|
|
||||||
instances: List[Klipper] = get_instances(Klipper)
|
instances: List[Klipper] = get_instances(Klipper)
|
||||||
svc = BackupService()
|
bm = BackupManager()
|
||||||
|
|
||||||
if not instances:
|
if not instances:
|
||||||
Logger.print_info("Unable to find directory to backup!")
|
Logger.print_info("Unable to find directory to backup!")
|
||||||
@@ -161,10 +166,10 @@ def backup_printer_config_dir() -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
svc.backup_directory(
|
bm.backup_directory(
|
||||||
source_path=instance.base.cfg_dir,
|
instance.data_dir.name,
|
||||||
target_path=f"{instance.data_dir.name}",
|
source=instance.base.cfg_dir,
|
||||||
backup_name="config",
|
target=PRINTER_DATA_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# This file acts as an example file.
|
|
||||||
#
|
|
||||||
# 1) Make a copy of this file and rename it to 'klipper_repos.txt'
|
|
||||||
# 2) Add your custom Klipper repository to the bottom of that copy
|
|
||||||
# 3) Save the file
|
|
||||||
#
|
|
||||||
# Back in KIAUH you can now go into -> [Settings] and use action '2' to set a different Klipper repository
|
|
||||||
#
|
|
||||||
# Make sure to always separate the repository and the branch with a ','.
|
|
||||||
# <repository>,<branch> -> https://github.com/Klipper3d/klipper,master
|
|
||||||
# If you omit a branch, it will always default to 'master'
|
|
||||||
#
|
|
||||||
# You are allowed to omit the 'https://github.com/' part of the repository URL
|
|
||||||
# Down below are now a few examples of what is considered as valid:
|
|
||||||
https://github.com/Klipper3d/klipper,master
|
|
||||||
https://github.com/Klipper3d/klipper
|
|
||||||
Klipper3d/klipper,master
|
|
||||||
Klipper3d/klipper
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev=["ruff", "mypy"]
|
dev=["ruff", "pyright"]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
required-version = ">=0.9.10"
|
required-version = ">=0.9.10"
|
||||||
@@ -20,14 +20,3 @@ quote-style = "double"
|
|||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
extend-select = ["I"]
|
extend-select = ["I"]
|
||||||
|
|
||||||
[tool.mypy]
|
|
||||||
python_version = "3.8"
|
|
||||||
platform = "linux"
|
|
||||||
# strict = true # TODO: enable this once everything is else is handled
|
|
||||||
check_untyped_defs = true
|
|
||||||
ignore_missing_imports = true
|
|
||||||
warn_redundant_casts = true
|
|
||||||
warn_unused_ignores = true
|
|
||||||
warn_return_any = true
|
|
||||||
warn_unreachable = true
|
|
||||||
|
|||||||
@@ -153,20 +153,11 @@ import shlex
|
|||||||
import re
|
import re
|
||||||
import pathlib
|
import pathlib
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
|
||||||
from typing import Tuple, Dict, List, Any
|
from typing import Tuple, Dict, List, Any
|
||||||
|
|
||||||
def _get_distro_info() -> Dict[str, Any]:
|
def _get_distro_info() -> Dict[str, Any]:
|
||||||
try:
|
|
||||||
import distro
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
return dict(
|
|
||||||
distro_id=distro.id(),
|
|
||||||
distro_version=distro.version(),
|
|
||||||
aliases=distro.like().split()
|
|
||||||
)
|
|
||||||
release_file = pathlib.Path("/etc/os-release")
|
release_file = pathlib.Path("/etc/os-release")
|
||||||
release_info: Dict[str, str] = {}
|
release_info: Dict[str, str] = {}
|
||||||
with release_file.open("r") as f:
|
with release_file.open("r") as f:
|
||||||
@@ -202,9 +193,6 @@ class SysDepsParser:
|
|||||||
version = distro_info.get("distro_version")
|
version = distro_info.get("distro_version")
|
||||||
if version:
|
if version:
|
||||||
self.distro_version = _convert_version(version)
|
self.distro_version = _convert_version(version)
|
||||||
self.vendor: str = ""
|
|
||||||
if pathlib.Path("/etc/rpi-issue").is_file():
|
|
||||||
self.vendor = "raspberry-pi"
|
|
||||||
|
|
||||||
def _parse_spec(self, full_spec: str) -> str | None:
|
def _parse_spec(self, full_spec: str) -> str | None:
|
||||||
parts = full_spec.split(";", maxsplit=1)
|
parts = full_spec.split(";", maxsplit=1)
|
||||||
@@ -249,9 +237,6 @@ class SysDepsParser:
|
|||||||
elif req_var == "distro_id":
|
elif req_var == "distro_id":
|
||||||
left_op: str | Tuple[int | str, ...] = self.distro_id
|
left_op: str | Tuple[int | str, ...] = self.distro_id
|
||||||
right_op = dep_parts[2].strip().strip("\"'")
|
right_op = dep_parts[2].strip().strip("\"'")
|
||||||
elif req_var == "vendor":
|
|
||||||
left_op = self.vendor
|
|
||||||
right_op = dep_parts[2].strip().strip("\"'")
|
|
||||||
elif req_var == "distro_version":
|
elif req_var == "distro_version":
|
||||||
if not self.distro_version:
|
if not self.distro_version:
|
||||||
logging.info(
|
logging.info(
|
||||||
@@ -320,12 +305,12 @@ system_deps = {
|
|||||||
"python3-virtualenv", "python3-dev", "libopenjp2-7", "libsodium-dev",
|
"python3-virtualenv", "python3-dev", "libopenjp2-7", "libsodium-dev",
|
||||||
"zlib1g-dev", "libjpeg-dev", "packagekit",
|
"zlib1g-dev", "libjpeg-dev", "packagekit",
|
||||||
"wireless-tools; distro_id != 'ubuntu' or distro_version <= '24.04'",
|
"wireless-tools; distro_id != 'ubuntu' or distro_version <= '24.04'",
|
||||||
"iw; distro_id == 'ubuntu' and distro_version >= '24.10'",
|
"iw; distro_id == 'ubuntu' and distro_version >= '24.10'", "curl",
|
||||||
"python3-libcamera; vendor == 'raspberry-pi' and distro_version >= '11'",
|
"build-essential"
|
||||||
"curl", "build-essential"
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
# *** SYSTEM DEPENDENCIES END ***
|
system_deps_json = pathlib.Path("$package_json")
|
||||||
|
system_deps = json.loads(system_deps_json.read_bytes())
|
||||||
parser = SysDepsParser()
|
parser = SysDepsParser()
|
||||||
pkgs = parser.parse_dependencies(system_deps)
|
pkgs = parser.parse_dependencies(system_deps)
|
||||||
if pkgs:
|
if pkgs:
|
||||||
|
|||||||
Reference in New Issue
Block a user