diff --git a/pmb/chroot/init.py b/pmb/chroot/init.py index bc6c0351..42133781 100644 --- a/pmb/chroot/init.py +++ b/pmb/chroot/init.py @@ -114,10 +114,17 @@ def init(chroot: Chroot, usr_merge=UsrMerge.AUTO): config = get_context().config + # If the channel is wrong and the user has auto_zap_misconfigured_chroots + # enabled, zap the chroot and reinitialize it + if chroot.exists(): + zap = pmb.config.workdir.chroot_check_channel(chroot) + if zap: + pmb.chroot.del_chroot(chroot.path, confirm=False) + pmb.config.workdir.clean() + pmb.chroot.mount(chroot) mark_in_chroot(chroot) if chroot.exists(): - pmb.config.workdir.chroot_check_channel(chroot) copy_resolv_conf(chroot) pmb.chroot.apk.update_repository_list(chroot) warn_if_chroot_is_outdated(chroot) diff --git a/pmb/config/__init__.py b/pmb/config/__init__.py index 76d2329d..d170ea5f 100644 --- a/pmb/config/__init__.py +++ b/pmb/config/__init__.py @@ -72,11 +72,10 @@ def sudo(cmd: Sequence[PathString]) -> Sequence[PathString]: return cmd -defaults = { +defaults: Dict[str, PathString] = { "cipher": "aes-xts-plain64", "config": Path((os.environ.get('XDG_CONFIG_HOME') or os.path.expanduser("~/.config")) + "/pmbootstrap.cfg"), - "fork_alpine": False, # A higher value is typically desired, but this can lead to VERY long open # times on slower devices due to host systems being MUCH faster than the # target device (see issue #429). diff --git a/pmb/config/workdir.py b/pmb/config/workdir.py index 66702f81..0c1525ef 100644 --- a/pmb/config/workdir.py +++ b/pmb/config/workdir.py @@ -14,6 +14,7 @@ import pmb.config.pmaports from pmb.core import Chroot from pmb.core.context import get_context from pmb.core.pkgrepo import pkgrepo_default_path +from pmb.helpers import logging def chroot_save_init(suffix: Chroot): @@ -69,9 +70,15 @@ def chroots_outdated(chroot: Optional[Chroot]=None): return False -def chroot_check_channel(chroot: Chroot): - path = get_context().config.work / "workdir.cfg" - msg_again = "Run 'pmbootstrap zap' to delete your chroots and try again." +def chroot_check_channel(chroot: Chroot) -> bool: + """Check the chroot channel against the current channel. Returns + True if the chroot should be zapped (both that it needs zapping and + the user has auto_zap_misconfigured_chroots enabled), False otherwise.""" + config = get_context().config + path = config.work / "workdir.cfg" + msg_again = "Run 'pmbootstrap zap' to delete your chroots and try again." \ + " To do this automatically, run 'pmbootstrap config" \ + " auto_zap_misconfigured_chroots yes'." msg_unknown = ("Could not figure out on which release channel the" f" '{chroot}' chroot is.") if not os.path.exists(path): @@ -85,10 +92,23 @@ def chroot_check_channel(chroot: Chroot): channel = pmb.config.pmaports.read_config()["channel"] channel_cfg = cfg[key][str(chroot)] + msg = f"Chroot '{chroot}' is for the '{channel_cfg}' channel," \ + f" but you are on the '{channel}' channel." + if channel != channel_cfg: - raise RuntimeError(f"Chroot '{chroot}' was created for the" - f" '{channel_cfg}' channel, but you are on the" - f" '{channel}' channel now. {msg_again}") + if config.auto_zap_misconfigured_chroots.enabled(): + if config.auto_zap_misconfigured_chroots.noisy(): + logging.info(msg) + logging.info("Automatically zapping since" + " auto_zap_misconfigured_chroots is enabled.") + logging.info("NOTE: You can silence this message with 'pmbootstrap" + " config auto_zap_misconfigured_chroots silently'") + else: + logging.debug(f"{msg} Zapping chroot.") + return True + raise RuntimeError(f"{msg} {msg_again}") + + return False def clean(): diff --git a/pmb/core/config.py b/pmb/core/config.py index 4c3aeb7d..8982918e 100644 --- a/pmb/core/config.py +++ b/pmb/core/config.py @@ -26,6 +26,18 @@ class SystemdConfig(enum.Enum): return [e.value for e in SystemdConfig] +class AutoZapConfig(enum.StrEnum): + NO = "no" + YES = "yes" + SILENTLY = "silently" + + def enabled(self) -> bool: + return self != AutoZapConfig.NO + + def noisy(self) -> bool: + return self == AutoZapConfig.YES + + class Config(): aports: List[Path] = [Path(os.path.expanduser("~") + "/.local/var/pmbootstrap/cache_git/pmaports")] @@ -57,6 +69,8 @@ class Config(): ui_extras: bool = False user: str = "user" work: Path = Path(os.path.expanduser("~") + "/.local/var/pmbootstrap") + # automatically zap chroots that are for the wrong channel + auto_zap_misconfigured_chroots: AutoZapConfig = AutoZapConfig.NO providers: Dict[str, str] = { }