feat: implement three-way /etc merge

This commit is contained in:
Rudra Saraswat 2024-02-09 13:55:45 +05:30
parent 7c53002545
commit deb302a20e
2 changed files with 63 additions and 52 deletions

67
akshara
View file

@ -22,6 +22,7 @@ import sys
import time import time
import yaml import yaml
import shutil import shutil
import filecmp
import argparse import argparse
import requests import requests
import platform import platform
@ -71,8 +72,6 @@ class colors:
cyan = '\033[46m' cyan = '\033[46m'
lightgrey = '\033[47m' lightgrey = '\033[47m'
# END
def exec(*cmd, **kwargs): def exec(*cmd, **kwargs):
return subprocess.call(cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr, **kwargs) return subprocess.call(cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr, **kwargs)
@ -197,6 +196,10 @@ def update_system():
'blend-files' 'blend-files'
] ]
keep = [
'/usr/share'
]
if (type(blend_release.get('impl')) == str and if (type(blend_release.get('impl')) == str and
type(blend_release.get('track')) != 'custom'): type(blend_release.get('track')) != 'custom'):
res = interpret_track(blend_release) res = interpret_track(blend_release)
@ -292,21 +295,22 @@ Server = {package_repo["repo-url"]}
break break
counter = 0 counter = 0
while True: if aur_packages != []:
exec_chroot('useradd', '-m', '-G', 'wheel', '-s', '/bin/bash', 'aur') while True:
exec_chroot('bash', '-c', 'echo "aur ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/aur') exec_chroot('useradd', '-m', '-G', 'wheel', '-s', '/bin/bash', 'aur')
return_val = exec_chroot( exec_chroot('bash', '-c', 'echo "aur ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/aur')
'runuser', '-u', 'aur', '--', 'paru', '-Sy', '--noconfirm', '--needed', return_val = exec_chroot(
'--noprogressbar', '--skipreview', '--removemake', '--cleanafter', '--ask=4', 'runuser', '-u', 'aur', '--', 'paru', '-Sy', '--noconfirm', '--needed',
*blend_release.get('aur-packages')) '--noprogressbar', '--skipreview', '--removemake', '--cleanafter', '--ask=4',
exec_chroot('userdel', '-r', 'aur') *aur_packages)
exec_chroot('rm', '-f', '/etc/sudoers.d/aur') exec_chroot('userdel', '-r', 'aur')
counter += 1 exec_chroot('rm', '-f', '/etc/sudoers.d/aur')
if counter > 30: counter += 1
error('failed to download AUR packages') if counter > 30:
exit(50) error('failed to download AUR packages')
if return_val == 0: exit(50)
break if return_val == 0:
break
for service in services: for service in services:
if type(service) is str: if type(service) is str:
@ -344,6 +348,35 @@ Server = {package_repo["repo-url"]}
exec_chroot('mkinitcpio', '-P') exec_chroot('mkinitcpio', '-P')
exec('cp', '-ax', '/.new_rootfs/etc', '/.new.etc')
etc_diff = filecmp.dircmp('/etc/', '/usr/etc/')
def get_diff_etc_files(dcmp):
dir_name = dcmp.left.replace('/etc/', '/.new.etc/', 1)
for name in dcmp.left_only:
exec('mkdir', '-p', dir_name)
exec('cp', '-ax', os.path.join(dcmp.left, name), dir_name)
for name in dcmp.diff_files:
exec('cp', '-ax', os.path.join(dcmp.left, name), dir_name)
for sub_dcmp in dcmp.subdirs.values():
get_diff_etc_files(sub_dcmp)
get_diff_etc_files(etc_diff)
exec('cp', '-ax', '/var/lib', '/.new.var.lib')
var_lib_diff = filecmp.dircmp('/.new_rootfs/var/lib/', '/.new.var.lib/')
dir_name = '/.new.var.lib/'
for name in var_lib_diff.left_only:
if os.path.isdir(os.path.join(var_lib_diff.left, name)):
exec('cp', '-ax', os.path.join(var_lib_diff.left, name), dir_name)
for name in var_lib_diff.right_only:
exec('rm', '-rf', os.path.join(dir_name, name))
exec('cp', '/.new_rootfs/etc/pacman.conf', '/.new.etc')
exec('mv', '.new_rootfs', '.update_rootfs') exec('mv', '.new_rootfs', '.update_rootfs')
new_boot_files = [] new_boot_files = []

View file

@ -12,42 +12,20 @@ run_latehook() {
mv /new_root/usr /new_root/.old.usr mv /new_root/usr /new_root/.old.usr
mv /new_root/.update_rootfs/usr /new_root/usr mv /new_root/.update_rootfs/usr /new_root/usr
# Same for /var/cache/pacman. # Same for /etc.
mv /new_root/var/cache/pacman /new_root/.old.pacmancache if [[ -d /new_root/.update_rootfs/etc ]]; then
mv /new_root/.update_rootfs/var/cache/pacman /new_root/var/cache mv /new_root/.update_rootfs/etc /new_root/usr/etc
fi
if [[ -d /new_root/.new.etc ]]; then
mv /new_root/etc /new_root/.old.etc
mv /new_root/.new.etc /new_root/etc
fi
# Same for /var/lib/pacman. # Same for /var/lib/pacman.
mv /new_root/var/lib/pacman /new_root/.old.var.lib.pacman if [[ -d /new_root/.new.var.lib ]]; then
mv /new_root/.update_rootfs/var/lib/pacman /new_root/var/lib mv /new_root/var/lib /new_root/.old.var.lib
mv /new_root/.new.var.lib /new_root/var/lib
# Move to /etc stage. fi
touch /new_root/.etc-stage
fi
# Detect if /etc stage is active.
if [[ -f /new_root/.etc-stage ]]; then
# Create new /etc.
rm -rf /new_root/.new_etc; cp -a /new_root/etc /new_root/.new_etc
(cd /new_root/.new_etc && find . -type f | grep -Fxv -f <(cd "/new_root/.update_rootfs/etc" && find . -type f) | xargs rm -f)
(cd /new_root/.new_etc && find . -type l | grep -Fxv -f <(cd "/new_root/.update_rootfs/etc" && find . -type l) | grep -Fxv './localtime' | xargs rm -f)
mkdir -p /.old.varlib
(cd /new_root/var/lib && find . -maxdepth 1 -type d | grep -Fxv -f <(cd "/new_root/.update_rootfs/var/lib" && find . -maxdepth 1 -type d) | grep -Fxv './pacman' | xargs sh -c 'mv "$@" /new_root/.old.varlib' sh)
(cd /new_root/.update_rootfs/var/lib && find . -maxdepth 1 -type d | grep -Fxv -f <(cd "/new_root/var/lib" && find . -maxdepth 1 -type d) | xargs sh -c 'cp -r "$@" /new_root/var/lib' sh)
cp /new_root/.update_rootfs/etc/pacman.conf /new_root/.new_etc/pacman.conf
rm -rf /new_root/.new_etc/pacman.d
cp -a /new_root/.update_rootfs/etc/pacman.d /new_root/.new_etc/pacman.d
rm -rf /new_root/.new_etc/sudoers.d
cp -a /new_root/etc/sudoers.d /new_root/.new_etc
(cd /new_root/.update_rootfs/etc && find . -type f | grep -Fxv -f <(cd "/new_root/.new_etc" && find . -type f) | xargs -n 1 sh -c 'mkdir -p "/new_root/.new_etc/$(dirname "$1")"; cp -a "$1" /new_root/.new_etc/$(dirname "$1")' sh)
(cd /new_root/.update_rootfs/etc && find . -type l | grep -Fxv -f <(cd "/new_root/.new_etc" && find . -type l) | xargs -n 1 sh -c 'mkdir -p "/new_root/.new_etc/$(dirname "$1")"; cp -a "$1" /new_root/.new_etc/$(dirname "$1")' sh)
mv /new_root/etc /new_root/.old.etc || :
mv /new_root/.new_etc /new_root/etc
mv /new_root/etc/systemd/system /new_root/.old.etc.systemd.system
mv /new_root/.update_rootfs/etc/systemd/system /new_root/etc/systemd
# Successful update.
rm -f /new_root/.etc-stage
mv /new_root/.update_rootfs /new_root/.old.update_rootfs mv /new_root/.update_rootfs /new_root/.old.update_rootfs
touch /new_root/.successful-update touch /new_root/.successful-update