diff --git a/archinstall/__init__.py b/archinstall/__init__.py index 7e086e6e34..dd2bf8d3e8 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -8,6 +8,7 @@ from archinstall.lib.args import arch_config_handler from archinstall.lib.disk.utils import disk_layouts +from archinstall.lib.packages.packages import check_package_upgrade from .lib.hardware import SysInfo from .lib.output import FormattedOutput, debug, error, info, log, warn @@ -53,15 +54,15 @@ def _check_new_version() -> None: info('Checking version...') upgrade = None - try: - upgrade = Pacman.run('-Qu archinstall').decode() - except Exception as e: - debug(f'Failed determine pacman version: {e}') + upgrade = check_package_upgrade('archinstall') + + if upgrade is None: + debug('No archinstall upgrades found') + return None - if upgrade: - text = f'New version available: {upgrade}' - info(text) - time.sleep(3) + text = tr('New version available') + f': {upgrade}' + info(text) + time.sleep(3) def main() -> int: diff --git a/archinstall/lib/disk/disk_menu.py b/archinstall/lib/disk/disk_menu.py index 81ce895e64..09dcd55e89 100644 --- a/archinstall/lib/disk/disk_menu.py +++ b/archinstall/lib/disk/disk_menu.py @@ -94,8 +94,8 @@ def _define_menu_options(self) -> list[MenuItem]: ] @override - def run(self) -> DiskLayoutConfiguration | None: - super().run() + def run(self, additional_title: str | None = None) -> DiskLayoutConfiguration | None: + super().run(additional_title=additional_title) if self._disk_menu_config.disk_config: self._disk_menu_config.disk_config.lvm_config = self._disk_menu_config.lvm_config diff --git a/archinstall/lib/disk/encryption_menu.py b/archinstall/lib/disk/encryption_menu.py index c664ba6e19..738fc019a6 100644 --- a/archinstall/lib/disk/encryption_menu.py +++ b/archinstall/lib/disk/encryption_menu.py @@ -115,8 +115,8 @@ def _check_dep_lvm_vols(self) -> bool: return False @override - def run(self) -> DiskEncryption | None: - super().run() + def run(self, additional_title: str | None = None) -> DiskEncryption | None: + super().run(additional_title=additional_title) enc_type: EncryptionType | None = self._item_group.find_by_key('encryption_type').value enc_password: Password | None = self._item_group.find_by_key('encryption_password').value diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 222c689777..1763247307 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -60,8 +60,11 @@ def _prev_locale(self, item: MenuItem) -> str: return temp_locale.preview() @override - def run(self) -> LocaleConfiguration: - super().run() + def run( + self, + additional_title: str | None = None, + ) -> LocaleConfiguration: + super().run(additional_title=additional_title) return self._locale_conf def _select_kb_layout(self, preset: str | None) -> str | None: diff --git a/archinstall/lib/menu/abstract_menu.py b/archinstall/lib/menu/abstract_menu.py index 3dfab04630..209e312007 100644 --- a/archinstall/lib/menu/abstract_menu.py +++ b/archinstall/lib/menu/abstract_menu.py @@ -94,7 +94,10 @@ def disable_all(self) -> None: def _is_config_valid(self) -> bool: return True - def run(self) -> ValueT | None: + def run( + self, + additional_title: str | None = None, + ) -> ValueT | None: self._sync_from_config() while True: @@ -106,6 +109,7 @@ def run(self) -> ValueT | None: preview_style=PreviewStyle.RIGHT, preview_size='auto', preview_frame=FrameProperties('Info', FrameStyle.MAX), + additional_title=additional_title, ).run() match result.type_: diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index 046f605fbc..741a8b6596 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -296,8 +296,8 @@ def _prev_custom_servers(self, item: MenuItem) -> str | None: return output.strip() @override - def run(self) -> MirrorConfiguration: - super().run() + def run(self, additional_title: str | None = None) -> MirrorConfiguration: + super().run(additional_title=additional_title) return self._mirror_config diff --git a/archinstall/lib/packages/packages.py b/archinstall/lib/packages/packages.py index c29e56789d..2ca0959815 100644 --- a/archinstall/lib/packages/packages.py +++ b/archinstall/lib/packages/packages.py @@ -105,7 +105,6 @@ def validate_package_list(packages: list[str]) -> tuple[list[str], list[str]]: def installed_package(package: str) -> LocalPackage | None: - package_info = [] try: package_info = Pacman.run(f'-Q --info {package}').decode().split('\n') return _parse_package_output(package_info, LocalPackage) @@ -115,6 +114,17 @@ def installed_package(package: str) -> LocalPackage | None: return None +@lru_cache +def check_package_upgrade(package: str) -> str | None: + try: + upgrade = Pacman.run(f'-Qu {package}').decode() + return upgrade + except SysCallError: + debug(f'Failed to check for package upgrades: {package}') + + return None + + @lru_cache def list_available_packages( repositories: tuple[Repository], diff --git a/archinstall/lib/profile/profile_menu.py b/archinstall/lib/profile/profile_menu.py index 5f4597c0ac..882b47e3c1 100644 --- a/archinstall/lib/profile/profile_menu.py +++ b/archinstall/lib/profile/profile_menu.py @@ -64,8 +64,8 @@ def _define_menu_options(self) -> list[MenuItem]: ] @override - def run(self) -> ProfileConfiguration | None: - super().run() + def run(self, additional_title: str | None = None) -> ProfileConfiguration | None: + super().run(additional_title=additional_title) return self._profile_config def _select_profile(self, preset: Profile | None) -> Profile | None: diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index 51b1264fed..e7d355e6d6 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -16,7 +16,9 @@ ) from archinstall.lib.models.users import User from archinstall.lib.output import debug, error, info +from archinstall.lib.packages.packages import check_package_upgrade from archinstall.lib.profile.profiles_handler import profile_handler +from archinstall.lib.translationhandler import tr from archinstall.tui import Tui @@ -27,13 +29,20 @@ def ask_user_questions() -> None: will we continue with the actual installation steps. """ + title_text = None + + upgrade = check_package_upgrade('archinstall') + if upgrade: + text = tr('New version available') + f': {upgrade}' + title_text = f' ({text})' + with Tui(): global_menu = GlobalMenu(arch_config_handler.config) if not arch_config_handler.args.advanced: global_menu.set_enabled('parallel_downloads', False) - global_menu.run() + global_menu.run(additional_title=title_text) def perform_installation(mountpoint: Path) -> None: diff --git a/archinstall/tui/curses_menu.py b/archinstall/tui/curses_menu.py index 2d1e2cbb93..32da868248 100644 --- a/archinstall/tui/curses_menu.py +++ b/archinstall/tui/curses_menu.py @@ -82,8 +82,8 @@ def _confirm_interrupt(self, warning: str) -> bool: return False - def help_entry(self) -> ViewportEntry: - return ViewportEntry(tr('Press Ctrl+h for help'), 0, 0, STYLE.NORMAL) + def help_text(self) -> str: + return tr('Press Ctrl+h for help') def _show_help(self) -> None: help_text = Help.get_help_text() @@ -488,7 +488,7 @@ def __init__( title = f'* {title}' if not self._allow_skip else title self._frame = FrameProperties(title, FrameStyle.MAX) - self._help_vp: Viewport | None = None + self._title_vp: Viewport | None = None self._header_vp: Viewport | None = None self._input_vp: EditViewport | None = None self._info_vp: Viewport | None = None @@ -507,7 +507,7 @@ def __init__( def _init_viewports(self) -> None: y_offset = 0 - self._help_vp = Viewport(self._max_width, 2, 0, y_offset) + self._title_vp = Viewport(self._max_width, 2, 0, y_offset) y_offset += 2 if self._header_entries: @@ -543,8 +543,8 @@ def resize_win(self) -> None: self._draw() def _clear_all(self) -> None: - if self._help_vp: - self._help_vp.erase() + if self._title_vp: + self._title_vp.erase() if self._header_vp: self._header_vp.erase() if self._input_vp: @@ -572,8 +572,10 @@ def _get_input_text(self) -> str | None: return text def _draw(self) -> None: - if self._help_vp: - self._help_vp.update([self.help_entry()], 0) + if self._title_vp: + help_text = self.help_text() + help_entry = ViewportEntry(help_text, 0, 0, STYLE.NORMAL) + self._title_vp.update([help_entry], 0) if self._header_entries and self._header_vp: self._header_vp.update(self._header_entries, 0) @@ -692,6 +694,7 @@ def __init__( preview_style: PreviewStyle = PreviewStyle.NONE, preview_size: float | Literal['auto'] = 0.2, preview_frame: FrameProperties | None = None, + additional_title: str | None = None, ): super().__init__() @@ -712,6 +715,7 @@ def __init__( self._frame = frame self._interrupt_warning = reset_warning_msg self._header = header + self._additional_title = additional_title self._header_entries = [] if header: @@ -730,7 +734,7 @@ def __init__( self._visible_entries: list[ViewportEntry] = [] self._max_height, self._max_width = Tui.t().max_yx - self._help_vp: Viewport | None = None + self._title_vp: Viewport | None = None self._header_vp: Viewport | None = None self._footer_vp: Viewport | None = None self._menu_vp: Viewport | None = None @@ -787,8 +791,8 @@ def _clear_all(self) -> None: self._preview_vp.erase() if self._footer_vp: self._footer_vp.erase() - if self._help_vp: - self._help_vp.erase() + if self._title_vp: + self._title_vp.erase() def _footer_entries(self) -> list[ViewportEntry]: if self._active_search: @@ -801,7 +805,7 @@ def _init_viewports(self, arg_prev_size: float | Literal['auto']) -> None: footer_height = 2 # possible filter at the bottom y_offset = 0 - self._help_vp = Viewport(self._max_width, 2, 0, y_offset) + self._title_vp = Viewport(self._max_width, 2, 0, y_offset) y_offset += 2 if self._header_entries: @@ -933,8 +937,15 @@ def _draw(self) -> None: items = self._items_state.get_view_items() vp_entries = self._item_to_vp_entry(items) - if self._help_vp: - self._update_viewport(self._help_vp, [self.help_entry()]) + if self._title_vp: + title_text = self.help_text() + + if self._additional_title is not None: + title_text += f' {self._additional_title}' + + title_vp_entry = ViewportEntry(title_text, 0, 0, STYLE.NORMAL) + + self._update_viewport(self._title_vp, [title_vp_entry]) if self._header_vp: self._update_viewport(self._header_vp, self._header_entries)