diff --git a/archinstall/__init__.py b/archinstall/__init__.py index e5c2e55218..0050a1fde4 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -1,150 +1,3 @@ -"""Arch Linux installer - guided, templates etc.""" +from .lib.plugins import plugin -import importlib -import os -import sys -import time -import traceback - -from archinstall.lib.args import arch_config_handler -from archinstall.lib.disk.utils import disk_layouts -from archinstall.lib.general import running_from_host -from archinstall.lib.network.wifi_handler import wifi_handler -from archinstall.lib.networking import ping -from archinstall.lib.packages.packages import check_version_upgrade - -from .lib.hardware import SysInfo -from .lib.output import FormattedOutput, debug, error, info, log, warn -from .lib.pacman import Pacman -from .lib.plugins import load_plugin, plugins -from .lib.translationhandler import Language, tr, translation_handler - - -# @archinstall.plugin decorator hook to programmatically add -# plugins in runtime. Useful in profiles_bck and other things. -def plugin(f, *args, **kwargs) -> None: # type: ignore[no-untyped-def] - plugins[f.__name__] = f - - -def _log_sys_info() -> None: - # Log various information about hardware before starting the installation. This might assist in troubleshooting - debug(f'Hardware model detected: {SysInfo.sys_vendor()} {SysInfo.product_name()}; UEFI mode: {SysInfo.has_uefi()}') - debug(f'Processor model detected: {SysInfo.cpu_model()}') - debug(f'Memory statistics: {SysInfo.mem_available()} available out of {SysInfo.mem_total()} total installed') - debug(f'Virtualization detected: {SysInfo.virtualization()}; is VM: {SysInfo.is_vm()}') - debug(f'Graphics devices detected: {SysInfo._graphics_devices().keys()}') - - # For support reasons, we'll log the disk layout pre installation to match against post-installation layout - debug(f'Disk states before installing:\n{disk_layouts()}') - - -def _check_online() -> None: - try: - ping('1.1.1.1') - except OSError as ex: - if 'Network is unreachable' in str(ex): - if not arch_config_handler.args.skip_wifi_check: - success = not wifi_handler.setup() - if not success: - sys.exit(0) - - -def _fetch_arch_db() -> None: - info('Fetching Arch Linux package database...') - try: - Pacman.run('-Sy') - except Exception as e: - error('Failed to sync Arch Linux package database.') - if 'could not resolve host' in str(e).lower(): - error('Most likely due to a missing network connection or DNS issue.') - - error('Run archinstall --debug and check /var/log/archinstall/install.log for details.') - - debug(f'Failed to sync Arch Linux package database: {e}') - sys.exit(1) - - -def main() -> int: - """ - This can either be run as the compiled and installed application: python setup.py install - OR straight as a module: python -m archinstall - In any case we will be attempting to load the provided script to be run from the scripts/ folder - """ - if '--help' in sys.argv or '-h' in sys.argv: - arch_config_handler.print_help() - return 0 - - if os.getuid() != 0: - print(tr('Archinstall requires root privileges to run. See --help for more.')) - return 1 - - _log_sys_info() - - if not arch_config_handler.args.offline: - _check_online() - _fetch_arch_db() - - if not arch_config_handler.args.skip_version_check: - upgrade = check_version_upgrade() - - if upgrade: - text = tr('New version available') + f': {upgrade}' - info(text) - time.sleep(3) - - if running_from_host(): - # log which mode we are using - debug('Running from Host (H2T Mode)...') - else: - debug('Running from ISO (Live Mode)...') - - script = arch_config_handler.get_script() - - mod_name = f'archinstall.scripts.{script}' - # by loading the module we'll automatically run the script - importlib.import_module(mod_name) - - return 0 - - -def run_as_a_module() -> None: - rc = 0 - exc = None - - try: - rc = main() - except Exception as e: - exc = e - finally: - if exc: - err = ''.join(traceback.format_exception(exc)) - error(err) - - text = ( - 'Archinstall experienced the above error. If you think this is a bug, please report it to\n' - 'https://github.com/archlinux/archinstall and include the log file "/var/log/archinstall/install.log".\n\n' - "Hint: To extract the log from a live ISO \ncurl -F 'file=@/var/log/archinstall/install.log' https://0x0.st\n" - ) - - warn(text) - rc = 1 - - sys.exit(rc) - - -__all__ = [ - 'FormattedOutput', - 'Language', - 'Pacman', - 'SysInfo', - 'arch_config_handler', - 'debug', - 'disk_layouts', - 'error', - 'info', - 'load_plugin', - 'log', - 'plugin', - 'translation_handler', - 'warn', -] +__all__ = ['plugin'] diff --git a/archinstall/__main__.py b/archinstall/__main__.py index c8a4779b2f..9065b8118a 100644 --- a/archinstall/__main__.py +++ b/archinstall/__main__.py @@ -1,4 +1,4 @@ -import archinstall +from archinstall.main import main if __name__ == '__main__': - archinstall.run_as_a_module() + main() diff --git a/archinstall/lib/plugins.py b/archinstall/lib/plugins.py index c4dd34899c..a9b19ae219 100644 --- a/archinstall/lib/plugins.py +++ b/archinstall/lib/plugins.py @@ -27,6 +27,12 @@ ) +# @archinstall.plugin decorator hook to programmatically add +# plugins in runtime. Useful in profiles_bck and other things. +def plugin(f, *args, **kwargs) -> None: # type: ignore[no-untyped-def] + plugins[f.__name__] = f + + def _localize_path(path: Path) -> Path: """ Support structures for load_plugin() diff --git a/archinstall/main.py b/archinstall/main.py new file mode 100644 index 0000000000..c577ddd239 --- /dev/null +++ b/archinstall/main.py @@ -0,0 +1,129 @@ +"""Arch Linux installer - guided, templates etc.""" + +import importlib +import os +import sys +import time +import traceback + +from archinstall.lib.args import arch_config_handler +from archinstall.lib.disk.utils import disk_layouts +from archinstall.lib.general import running_from_host +from archinstall.lib.network.wifi_handler import wifi_handler +from archinstall.lib.networking import ping +from archinstall.lib.packages.packages import check_version_upgrade + +from .lib.hardware import SysInfo +from .lib.output import debug, error, info, warn +from .lib.pacman import Pacman +from .lib.translationhandler import tr + + +def _log_sys_info() -> None: + # Log various information about hardware before starting the installation. This might assist in troubleshooting + debug(f'Hardware model detected: {SysInfo.sys_vendor()} {SysInfo.product_name()}; UEFI mode: {SysInfo.has_uefi()}') + debug(f'Processor model detected: {SysInfo.cpu_model()}') + debug(f'Memory statistics: {SysInfo.mem_available()} available out of {SysInfo.mem_total()} total installed') + debug(f'Virtualization detected: {SysInfo.virtualization()}; is VM: {SysInfo.is_vm()}') + debug(f'Graphics devices detected: {SysInfo._graphics_devices().keys()}') + + # For support reasons, we'll log the disk layout pre installation to match against post-installation layout + debug(f'Disk states before installing:\n{disk_layouts()}') + + +def _check_online() -> None: + try: + ping('1.1.1.1') + except OSError as ex: + if 'Network is unreachable' in str(ex): + if not arch_config_handler.args.skip_wifi_check: + success = not wifi_handler.setup() + if not success: + sys.exit(0) + + +def _fetch_arch_db() -> None: + info('Fetching Arch Linux package database...') + try: + Pacman.run('-Sy') + except Exception as e: + error('Failed to sync Arch Linux package database.') + if 'could not resolve host' in str(e).lower(): + error('Most likely due to a missing network connection or DNS issue.') + + error('Run archinstall --debug and check /var/log/archinstall/install.log for details.') + + debug(f'Failed to sync Arch Linux package database: {e}') + sys.exit(1) + + +def run() -> int: + """ + This can either be run as the compiled and installed application: python setup.py install + OR straight as a module: python -m archinstall + In any case we will be attempting to load the provided script to be run from the scripts/ folder + """ + if '--help' in sys.argv or '-h' in sys.argv: + arch_config_handler.print_help() + return 0 + + if os.getuid() != 0: + print(tr('Archinstall requires root privileges to run. See --help for more.')) + return 1 + + _log_sys_info() + + if not arch_config_handler.args.offline: + _check_online() + _fetch_arch_db() + + if not arch_config_handler.args.skip_version_check: + upgrade = check_version_upgrade() + + if upgrade: + text = tr('New version available') + f': {upgrade}' + info(text) + time.sleep(3) + + if running_from_host(): + # log which mode we are using + debug('Running from Host (H2T Mode)...') + else: + debug('Running from ISO (Live Mode)...') + + script = arch_config_handler.get_script() + + mod_name = f'archinstall.scripts.{script}' + # by loading the module we'll automatically run the script + importlib.import_module(mod_name) + + return 0 + + +def main() -> int: + rc = 0 + exc = None + + try: + rc = run() + except Exception as e: + exc = e + finally: + if exc: + err = ''.join(traceback.format_exception(exc)) + error(err) + + text = ( + 'Archinstall experienced the above error. If you think this is a bug, please report it to\n' + 'https://github.com/archlinux/archinstall and include the log file "/var/log/archinstall/install.log".\n\n' + "Hint: To extract the log from a live ISO \ncurl -F 'file=@/var/log/archinstall/install.log' https://0x0.st\n" + ) + + warn(text) + rc = 1 + + sys.exit(rc) + + +if __name__ == '__main__': + main() diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index f6eb2884e2..10cc49af0c 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -3,7 +3,6 @@ import time from pathlib import Path -from archinstall import SysInfo from archinstall.lib.applications.application_handler import application_handler from archinstall.lib.args import arch_config_handler from archinstall.lib.authentication.authentication_handler import auth_handler @@ -11,6 +10,7 @@ from archinstall.lib.disk.filesystem import FilesystemHandler from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.global_menu import GlobalMenu +from archinstall.lib.hardware import SysInfo from archinstall.lib.installer import Installer, accessibility_tools_in_use, run_custom_user_commands from archinstall.lib.interactions.general_conf import PostInstallationAction, ask_post_installation from archinstall.lib.models import Bootloader diff --git a/archinstall/scripts/only_hd.py b/archinstall/scripts/only_hd.py index ca7153303c..de113c5591 100644 --- a/archinstall/scripts/only_hd.py +++ b/archinstall/scripts/only_hd.py @@ -1,13 +1,13 @@ import sys from pathlib import Path -from archinstall import debug, error from archinstall.lib.args import arch_config_handler from archinstall.lib.configuration import ConfigurationOutput from archinstall.lib.disk.filesystem import FilesystemHandler from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.global_menu import GlobalMenu from archinstall.lib.installer import Installer +from archinstall.lib.output import debug, error def ask_user_questions() -> None: diff --git a/pyproject.toml b/pyproject.toml index 5262f5d667..d9e839eb48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ dev = [ doc = ["sphinx"] [project.scripts] -archinstall = "archinstall:run_as_a_module" +archinstall = "archinstall.main:main" [tool.setuptools.dynamic] readme = {file = ["README.rst", "USAGE.rst"]}