fix: bootloader update logic

This commit is contained in:
Rudra Saraswat 2026-04-04 00:01:45 +01:00
parent e439c02a0a
commit 2fdf50dfd2

View file

@ -35,6 +35,7 @@ def update_cleanup() -> None:
"-rf", "-rf",
"/var/cache/akshara/rootfs", "/var/cache/akshara/rootfs",
"/.update_rootfs", "/.update_rootfs",
"/.boot.bkp",
] ]
) )
@ -143,86 +144,116 @@ def merge_var(new_rootfs: RootFS, overrides_keep_new: dict) -> None:
) )
def handle_boot(new_rootfs, boot_config) -> None: def merge_into_tree(tree_root: str, tmp_tree_root: str) -> None:
"""Merge a new tree into an existing tree.
Args:
tree_root: String containing path to existing tree.
tmp_tree_root: String containing path to new tree.
"""
new_paths = []
for tmp_root, _, files in os.walk(tmp_tree_root):
root = tmp_root.replace(tmp_tree_root, tree_root, 1)
subprocess.run(["mkdir", "-p", root])
new_paths.append(root)
for path in files:
subprocess.run(["rm", "-rf", "--", os.path.join(root, path)])
subprocess.run(
[
"cp",
"-ax",
os.path.join(tmp_root, path),
os.path.join(root, path),
]
)
new_paths.append(os.path.join(root, path))
for root, _, files in os.walk(tree_root):
for path in files:
if os.path.join(root, path) not in new_paths:
subprocess.run(["rm", "-rf", "--", os.path.join(root, path)])
def handle_boot(new_rootfs: RootFS, boot_config: dict) -> None:
"""Handles /boot partition.""" """Handles /boot partition."""
subprocess.run(["rm", "-rf", "/.tmp.boot"]) subprocess.run(["rm", "-rf", "/.boot.bkp"])
subprocess.run(["cp", "-ax", os.path.join(str(new_rootfs), "boot"), "/.tmp.boot"]) subprocess.run(["cp", "-ax", "/boot", "/.boot.bkp"])
# Replace contents of /boot with those from new rootfs
# FIXME: should be atomic
merge_into_tree("/boot", os.path.join(str(new_rootfs), "boot"))
subprocess.run(["mount", "--bind", "/boot", f"{new_rootfs}/boot"])
def restore_old_boot():
subprocess.run(
["umount", "-l", f"{new_rootfs}/boot"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
merge_into_tree("/boot", "/.boot.bkp")
if boot_config["type"] == "bios": if boot_config["type"] == "bios":
if boot_config["loader"] == "grub": if boot_config["loader"] == "grub":
if ( if (
subprocess.run( new_rootfs.exec_chroot(
[ [
"grub-install", "grub-install",
f"--directory={os.path.join(str(new_rootfs), 'usr/lib/grub/i386-pc')}",
"--boot-directory=/.tmp.boot",
"--target=i386-pc", "--target=i386-pc",
boot_config["device"], boot_config["device"],
] ]
).returncode ).returncode
!= 0 != 0
): ):
output.error("aborting update...") restore_old_boot()
subprocess.run(["rm", "-rf", "/.tmp.boot"])
output.error("failed to install GRUB") output.error("failed to install GRUB")
output.error("aborted update")
exit(1) exit(1)
else: else:
subprocess.run(["umount", "-l", "/boot"]) restore_old_boot()
subprocess.run(["rm", "-rf", "/.tmp.boot"])
output.error("unsupported bootloader for BIOS configuration") output.error("unsupported bootloader for BIOS configuration")
output.error("aborted update")
exit(1) exit(1)
elif boot_config["type"] == "uefi": elif boot_config["type"] == "uefi":
if boot_config["loader"] == "grub": if boot_config["loader"] == "grub":
if ( if (
subprocess.run( new_rootfs.exec_chroot(
[ [
"grub-install", "grub-install",
f"--directory={os.path.join(str(new_rootfs), 'usr/lib/grub/x86_64-efi')}", "--efi-directory=/boot",
"--efi-directory=/.tmp.boot",
"--boot-directory=/.tmp.boot",
"--target=x86_64-efi", "--target=x86_64-efi",
"--removable", "--removable",
"--bootloader-id=blendOS", "--bootloader-id=blendOS",
] ]
) ).returncode
!= 0 != 0
): ):
output.error("aborting update...") restore_old_boot()
subprocess.run(["rm", "-rf", "/.tmp.boot"])
output.error("failed to install GRUB") output.error("failed to install GRUB")
output.error("aborted update")
exit(1) exit(1)
else: else:
subprocess.run(["rm", "-rf", "/.tmp.boot"]) restore_old_boot()
output.error("unsupported bootloader for BIOS configuration") output.error("unsupported bootloader for BIOS configuration")
output.error("aborted update")
exit(1) exit(1)
else: else:
subprocess.run(["umount", "-l", "/boot"]) restore_old_boot()
subprocess.run(["rm", "-rf", "/.tmp.boot"])
output.error(f"unsupported system type - {boot_config['type']}") output.error(f"unsupported system type - {boot_config['type']}")
output.error("aborted update")
exit(1) exit(1)
if boot_config["loader"] == "grub": if boot_config["loader"] == "grub":
new_rootfs.exec_chroot(["grub-mkconfig", "-o", "/grub.cfg"]) new_rootfs.exec_chroot(["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])
subprocess.run(["cp", f"{new_rootfs}/grub.cfg", "/.tmp.boot/grub/grub.cfg"])
# Replace /boot with /.tmp.boot subprocess.run(
# FIXME: should be atomic ["umount", "-l", f"{new_rootfs}/boot"],
for tmp_boot, dirs, files in os.walk("/.tmp.boot"): stdout=subprocess.DEVNULL,
boot = tmp_boot.replace("/.tmp.boot", "/boot", 1) stderr=subprocess.DEVNULL,
subprocess.run(["mkdir", "-p", boot]) )
for path in dirs + files: subprocess.run(["rm", "-rf", "/.boot.bkp"])
subprocess.run(["rm", "-rf", "--", os.path.join(boot, path)])
subprocess.run(
[
"cp",
"-ax",
os.path.join(tmp_boot, path),
os.path.join(boot, path),
]
)
subprocess.run(["rm", "-rf", "/.tmp.boot"])
def update() -> None: def update() -> None: