From 3016822c26e01a1538eca97409c91530253df20b Mon Sep 17 00:00:00 2001 From: xhdndmm Date: Mon, 6 Apr 2026 06:27:55 +0800 Subject: [PATCH 1/3] add mirror source switching functionality during slow database sync --- archinstall/main.py | 60 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/archinstall/main.py b/archinstall/main.py index ac072b0e84..d1833fb6eb 100644 --- a/archinstall/main.py +++ b/archinstall/main.py @@ -11,6 +11,10 @@ from archinstall.lib.args import ArchConfigHandler from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.hardware import SysInfo +from archinstall.lib.installer import Installer +from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType +from archinstall.lib.mirror.mirror_handler import MirrorListHandler +from archinstall.lib.mirror.mirror_menu import MirrorMenu from archinstall.lib.network.wifi_handler import WifiHandler from archinstall.lib.networking import ping from archinstall.lib.output import debug, error, info, warn @@ -46,11 +50,60 @@ def _check_online(wifi_handler: WifiHandler | None = None) -> bool: return True -def _fetch_arch_db() -> bool: +SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS = 15 + + +def _confirm_switch_mirror_sources(elapsed_seconds: float) -> bool: + if not sys.stdin.isatty(): + return False + + prompt = tr('Refreshing repositories is taking a long time ({} seconds). Would you like to switch mirror sources? (Y/n): ').format(int(elapsed_seconds)) + try: + return input(prompt).strip().lower() in ('y', 'yes', '') + except EOFError: + return False + + +def _switch_mirror_sources() -> bool: + info(tr('Switching mirror sources.')) + mirror_list_handler = MirrorListHandler() + + try: + mirror_configuration = tui.run(lambda: MirrorMenu(mirror_list_handler).run()) + except Exception as e: + error(tr('Could not open mirror configuration menu.')) + debug(f'Failed to switch mirror sources: {e}') + return False + + if mirror_configuration is None: + warn(tr('Mirror source selection cancelled.')) + return False + + try: + installer = Installer( + Path('/'), + DiskLayoutConfiguration(DiskLayoutType.Pre_mount, mountpoint=Path('/')), + ) + installer.set_mirrors(mirror_list_handler, mirror_configuration, on_target=False) + info(tr('Mirror sources have been updated.')) + return True + except Exception as e: + error(tr('Failed to update the local mirror list.')) + debug(f'Failed to update the mirror list: {e}') + return False + + +def _fetch_arch_db(retry: bool = False) -> bool: info('Fetching Arch Linux package database...') + started = time.time() try: Pacman.run('-Sy') except Exception as e: + elapsed = time.time() - started + if not retry and elapsed > SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS: + if _confirm_switch_mirror_sources(elapsed) and _switch_mirror_sources(): + return _fetch_arch_db(retry=True) + 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.') @@ -60,6 +113,11 @@ def _fetch_arch_db() -> bool: debug(f'Failed to sync Arch Linux package database: {e}') return False + elapsed = time.time() - started + if not retry and elapsed > SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS: + if _confirm_switch_mirror_sources(elapsed) and _switch_mirror_sources(): + return _fetch_arch_db(retry=True) + return True From 152ef49223b9474ad5a42dd78e19dce04bb35a7a Mon Sep 17 00:00:00 2001 From: xhdndmm Date: Tue, 7 Apr 2026 21:33:16 +0800 Subject: [PATCH 2/3] implement mirror source switching functionality --- archinstall/lib/switch_mirror.py | 52 ++++++++++++++++++++++++++++ archinstall/main.py | 58 +++----------------------------- 2 files changed, 57 insertions(+), 53 deletions(-) create mode 100644 archinstall/lib/switch_mirror.py diff --git a/archinstall/lib/switch_mirror.py b/archinstall/lib/switch_mirror.py new file mode 100644 index 0000000000..3022629a78 --- /dev/null +++ b/archinstall/lib/switch_mirror.py @@ -0,0 +1,52 @@ +from pathlib import Path + +from archinstall.lib.installer import Installer +from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType +from archinstall.lib.mirror.mirror_handler import MirrorListHandler +from archinstall.lib.mirror.mirror_menu import MirrorMenu +from archinstall.lib.network.wifi_handler import WifiHandler +from archinstall.lib.output import debug, error, info, warn +from archinstall.lib.translationhandler import tr +from archinstall.lib.networking import ping +from archinstall.tui.ui.components import tui + + +def check_online(wifi_handler: WifiHandler | None = None) -> bool: + try: + ping('1.1.1.1') + except OSError as ex: + if 'Network is unreachable' in str(ex): + if wifi_handler is not None: + result: bool = tui.run(wifi_handler) + if not result: + return False + + return True + +def switch_mirror_sources() -> bool: + info(tr('Switching mirror sources.')) + mirror_list_handler = MirrorListHandler() + + try: + mirror_configuration = tui.run(lambda: MirrorMenu(mirror_list_handler).run()) + except Exception as e: + error(tr('Could not open mirror configuration menu.')) + debug(f'Failed to switch mirror sources: {e}') + return False + + if mirror_configuration is None: + warn(tr('Mirror source selection cancelled.')) + return False + + try: + installer = Installer( + Path('/'), + DiskLayoutConfiguration(DiskLayoutType.Pre_mount, mountpoint=Path('/')), + ) + installer.set_mirrors(mirror_list_handler, mirror_configuration, on_target=False) + info(tr('Mirror sources have been updated.')) + return True + except Exception as e: + error(tr('Failed to update the local mirror list.')) + debug(f'Failed to update the mirror list: {e}') + return False diff --git a/archinstall/main.py b/archinstall/main.py index d1833fb6eb..51b2da83fe 100644 --- a/archinstall/main.py +++ b/archinstall/main.py @@ -11,18 +11,13 @@ from archinstall.lib.args import ArchConfigHandler from archinstall.lib.disk.utils import disk_layouts from archinstall.lib.hardware import SysInfo -from archinstall.lib.installer import Installer -from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType -from archinstall.lib.mirror.mirror_handler import MirrorListHandler -from archinstall.lib.mirror.mirror_menu import MirrorMenu from archinstall.lib.network.wifi_handler import WifiHandler -from archinstall.lib.networking import ping from archinstall.lib.output import debug, error, info, warn from archinstall.lib.packages.util import check_version_upgrade from archinstall.lib.pacman.pacman import Pacman from archinstall.lib.translationhandler import tr +from archinstall.lib.switch_mirror import check_online, switch_mirror_sources from archinstall.lib.utils.util import running_from_iso -from archinstall.tui.ui.components import tui def _log_sys_info() -> None: @@ -37,21 +32,7 @@ def _log_sys_info() -> None: debug(f'Disk states before installing:\n{disk_layouts()}') -def _check_online(wifi_handler: WifiHandler | None = None) -> bool: - try: - ping('1.1.1.1') - except OSError as ex: - if 'Network is unreachable' in str(ex): - if wifi_handler is not None: - result: bool = tui.run(wifi_handler) - if not result: - return False - - return True - - -SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS = 15 - +SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS = 10 def _confirm_switch_mirror_sources(elapsed_seconds: float) -> bool: if not sys.stdin.isatty(): @@ -64,35 +45,6 @@ def _confirm_switch_mirror_sources(elapsed_seconds: float) -> bool: return False -def _switch_mirror_sources() -> bool: - info(tr('Switching mirror sources.')) - mirror_list_handler = MirrorListHandler() - - try: - mirror_configuration = tui.run(lambda: MirrorMenu(mirror_list_handler).run()) - except Exception as e: - error(tr('Could not open mirror configuration menu.')) - debug(f'Failed to switch mirror sources: {e}') - return False - - if mirror_configuration is None: - warn(tr('Mirror source selection cancelled.')) - return False - - try: - installer = Installer( - Path('/'), - DiskLayoutConfiguration(DiskLayoutType.Pre_mount, mountpoint=Path('/')), - ) - installer.set_mirrors(mirror_list_handler, mirror_configuration, on_target=False) - info(tr('Mirror sources have been updated.')) - return True - except Exception as e: - error(tr('Failed to update the local mirror list.')) - debug(f'Failed to update the mirror list: {e}') - return False - - def _fetch_arch_db(retry: bool = False) -> bool: info('Fetching Arch Linux package database...') started = time.time() @@ -101,7 +53,7 @@ def _fetch_arch_db(retry: bool = False) -> bool: except Exception as e: elapsed = time.time() - started if not retry and elapsed > SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS: - if _confirm_switch_mirror_sources(elapsed) and _switch_mirror_sources(): + if _confirm_switch_mirror_sources(elapsed) and switch_mirror_sources(): return _fetch_arch_db(retry=True) error('Failed to sync Arch Linux package database.') @@ -115,7 +67,7 @@ def _fetch_arch_db(retry: bool = False) -> bool: elapsed = time.time() - started if not retry and elapsed > SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS: - if _confirm_switch_mirror_sources(elapsed) and _switch_mirror_sources(): + if _confirm_switch_mirror_sources(elapsed) and switch_mirror_sources(): return _fetch_arch_db(retry=True) return True @@ -161,7 +113,7 @@ def run() -> int: else: wifi_handler = None - if not _check_online(wifi_handler): + if not check_online(wifi_handler): return 0 if not _fetch_arch_db(): From 87db46aada6c21b9704ff072be014b26d24bf36e Mon Sep 17 00:00:00 2001 From: xhdndmm Date: Sat, 11 Apr 2026 11:35:46 +0800 Subject: [PATCH 3/3] move check_online function and update slow database sync threshold --- archinstall/lib/switch_mirror.py | 15 --------------- archinstall/main.py | 25 ++++++++++++++++++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/archinstall/lib/switch_mirror.py b/archinstall/lib/switch_mirror.py index 3022629a78..23e5cac28c 100644 --- a/archinstall/lib/switch_mirror.py +++ b/archinstall/lib/switch_mirror.py @@ -4,25 +4,10 @@ from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType from archinstall.lib.mirror.mirror_handler import MirrorListHandler from archinstall.lib.mirror.mirror_menu import MirrorMenu -from archinstall.lib.network.wifi_handler import WifiHandler from archinstall.lib.output import debug, error, info, warn from archinstall.lib.translationhandler import tr -from archinstall.lib.networking import ping from archinstall.tui.ui.components import tui - -def check_online(wifi_handler: WifiHandler | None = None) -> bool: - try: - ping('1.1.1.1') - except OSError as ex: - if 'Network is unreachable' in str(ex): - if wifi_handler is not None: - result: bool = tui.run(wifi_handler) - if not result: - return False - - return True - def switch_mirror_sources() -> bool: info(tr('Switching mirror sources.')) mirror_list_handler = MirrorListHandler() diff --git a/archinstall/main.py b/archinstall/main.py index 51b2da83fe..a4ee746317 100644 --- a/archinstall/main.py +++ b/archinstall/main.py @@ -16,8 +16,11 @@ from archinstall.lib.packages.util import check_version_upgrade from archinstall.lib.pacman.pacman import Pacman from archinstall.lib.translationhandler import tr -from archinstall.lib.switch_mirror import check_online, switch_mirror_sources +from archinstall.lib.switch_mirror import switch_mirror_sources from archinstall.lib.utils.util import running_from_iso +from archinstall.lib.networking import ping +from archinstall.lib.menu.helpers import Confirmation +from archinstall.tui.ui.components import tui def _log_sys_info() -> None: @@ -31,17 +34,29 @@ def _log_sys_info() -> None: # 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(wifi_handler: WifiHandler | None = None) -> bool: + try: + ping('1.1.1.1') + except OSError as ex: + if 'Network is unreachable' in str(ex): + if wifi_handler is not None: + result: bool = tui.run(wifi_handler) + if not result: + return False + + return True -SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS = 10 +SLOW_ARCH_DB_SYNC_THRESHOLD_SECONDS = 1 def _confirm_switch_mirror_sources(elapsed_seconds: float) -> bool: if not sys.stdin.isatty(): return False - prompt = tr('Refreshing repositories is taking a long time ({} seconds). Would you like to switch mirror sources? (Y/n): ').format(int(elapsed_seconds)) + header = tr('Refreshing repositories is taking a long time ({} seconds). Would you like to switch mirror sources?').format(int(elapsed_seconds)) try: - return input(prompt).strip().lower() in ('y', 'yes', '') - except EOFError: + result = tui.run(lambda: Confirmation(header).show()) + return result.get_value() is True + except Exception: return False