diff --git a/cache.py b/cache.py index 293051a..6ac2ab2 100644 --- a/cache.py +++ b/cache.py @@ -1,10 +1,11 @@ -import shutil import click import os -from config import config -from wrapper import enforce_wrap import logging +from config import config +from exec.file import remove_file +from wrapper import enforce_wrap + PATHS = ['chroots', 'pacman', 'jumpdrive', 'packages', 'images'] @@ -37,7 +38,4 @@ def cmd_clean(paths: list[str], force=False): for file in os.listdir(dir): path = os.path.join(dir, file) logging.debug(f'Removing "{path_name}/{file}"') - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.unlink(path) + remove_file(path, recursive=True) diff --git a/chroot/abstract.py b/chroot/abstract.py index f40b32c..2ff17d2 100644 --- a/chroot/abstract.py +++ b/chroot/abstract.py @@ -8,6 +8,7 @@ from typing import Protocol, Union, Optional, Mapping from uuid import uuid4 from exec.cmd import run_root_cmd, generate_env_cmd, flatten_shell_script, wrap_in_bash +from exec.file import root_write_file from config import config from constants import Arch, CHROOT_PATHS from distro.distro import get_base_distro, get_kupfer_local, RepoInfo @@ -272,8 +273,7 @@ class Chroot(AbstractChroot): filename = 'makepkg' + (f'_cross_{target_arch}' if cross else '') + '.conf' makepkg_conf_path_relative = os.path.join('etc', filename) makepkg_conf_path = os.path.join(self.path, makepkg_conf_path_relative) - with open(makepkg_conf_path, 'w') as f: - f.write(makepkg_cross_conf) + root_write_file(makepkg_conf_path, makepkg_cross_conf) return makepkg_conf_path_relative def write_pacman_conf(self, check_space: Optional[bool] = None): @@ -281,8 +281,7 @@ class Chroot(AbstractChroot): check_space = config.file['pacman']['check_space'] os.makedirs(self.get_path('/etc'), exist_ok=True) conf_text = get_base_distro(self.arch).get_pacman_conf(self.extra_repos, check_space=check_space) - with open(self.get_path('etc/pacman.conf'), 'w') as file: - file.write(conf_text) + root_write_file(self.get_path('etc/pacman.conf'), conf_text) def create_user( self, diff --git a/chroot/build.py b/chroot/build.py index d228ab6..1a8905a 100644 --- a/chroot/build.py +++ b/chroot/build.py @@ -8,6 +8,7 @@ from config import config from constants import Arch, GCC_HOSTSPECS, CROSSDIRECT_PKGS, CHROOT_PATHS from distro.distro import get_kupfer_local from exec.cmd import run_root_cmd +from exec.file import root_write_file, remove_file from .abstract import Chroot, get_chroot from .helpers import build_chroot_name @@ -51,8 +52,7 @@ class BuildChroot(Chroot): with open(self.get_path('/usr/bin/makepkg'), 'r') as file: data = file.read() data = data.replace('EUID == 0', 'EUID == -1') - with open(self.get_path('/usr/bin/makepkg'), 'w') as file: - file.write(data) + root_write_file(self.get_path('/usr/bin/makepkg'), data) # configure makepkg self.write_makepkg_conf(self.arch, cross_chroot_relative=None, cross=False) @@ -114,7 +114,7 @@ class BuildChroot(Chroot): rustc = os.path.join(native_chroot.path, 'usr/lib/crossdirect', target_arch, 'rustc') if os.path.exists(rustc): logging.debug('Disabling crossdirect rustc') - os.unlink(rustc) + remove_file(rustc) os.makedirs(native_mount, exist_ok=True) logging.debug(f'Mounting {native_chroot.name} to {native_mount}') diff --git a/exec/file.py b/exec/file.py index 8c33ace..fa16248 100644 --- a/exec/file.py +++ b/exec/file.py @@ -3,6 +3,7 @@ import os import stat import subprocess +from shutil import rmtree from typing import Optional, Union from .cmd import run_root_cmd, elevation_noop, generate_cmd_su, wrap_in_bash, shell_quote @@ -107,3 +108,14 @@ def root_write_file(*args, **kwargs): kwargs['user'] = 'root' kwargs['group'] = 'root' return write_file(*args, **kwargs) + + +def remove_file(path: str, recursive=False): + try: + rm = rmtree if recursive else os.unlink + rm(path) # type: ignore + except: + cmd = ['rm'] + (['-r'] if recursive else []) + [path] + rc = run_root_cmd(cmd).returncode + if rc: + raise Exception(f"Unable to remove {path}: cmd returned {rc}") diff --git a/image.py b/image.py index d07f4bf..b6df605 100644 --- a/image.py +++ b/image.py @@ -13,7 +13,8 @@ from chroot.device import DeviceChroot, get_device_chroot from constants import Arch, BASE_PACKAGES, DEVICES, FLAVOURS from config import config, Profile from distro.distro import get_base_distro, get_kupfer_https -from exec.cmd import run_root_cmd +from exec.cmd import run_root_cmd, generate_cmd_su +from exec.file import root_write_file from packages import build_enable_qemu_binfmt, discover_packages, build_packages from ssh import copy_ssh_keys from wrapper import enforce_wrap @@ -66,7 +67,7 @@ def shrink_fs(loop_device: str, file: str, sector_size: int): logging.debug(f'Shrinking partition at {loop_device}p2 to {sectors} sectors') child_proccess = subprocess.Popen( - ['sudo', 'fdisk', '-b', str(sector_size), loop_device], # TODO: replace hardcoded 'sudo' + generate_cmd_su(['fdisk', '-b', str(sector_size), loop_device], switch_user='root'), # type: ignore stdin=subprocess.PIPE, ) child_proccess.stdin.write('\n'.join([ # type: ignore @@ -332,8 +333,7 @@ def install_rootfs( 'etc/hostname': profile['hostname'], } for target, content in files.items(): - with open(os.path.join(chroot.path, target.lstrip('/')), 'w') as file: - file.write(content) + root_write_file(os.path.join(chroot.path, target.lstrip('/')), content) if post_cmds: result = chroot.run_cmd(' && '.join(post_cmds)) assert isinstance(result, subprocess.CompletedProcess) diff --git a/packages/__init__.py b/packages/__init__.py index 3d394d3..d18db74 100644 --- a/packages/__init__.py +++ b/packages/__init__.py @@ -16,6 +16,7 @@ from binfmt import register as binfmt_register from constants import REPOSITORIES, CROSSDIRECT_PKGS, QEMU_BINFMT_PKGS, GCC_HOSTSPECS, ARCHES, Arch, CHROOT_PATHS, MAKEPKG_CMD from config import config from exec.cmd import run_cmd, run_root_cmd +from exec.file import remove_file from chroot.build import get_build_chroot, BuildChroot from distro.distro import PackageInfo, get_kupfer_https, get_kupfer_local from ssh import run_ssh_command, scp_put_files @@ -299,13 +300,13 @@ def add_file_to_repo(file_path: str, repo_name: str, arch: Arch): file_path, repo_dir, ) - os.unlink(file_path) + remove_file(file_path) # clean up same name package from pacman cache cache_file = os.path.join(pacman_cache_dir, file_name) if os.path.exists(cache_file): logging.debug("Removing cached package file {cache_file}") - os.unlink(cache_file) + remove_file(cache_file) cmd = [ 'repo-add', '--remove', @@ -323,11 +324,11 @@ def add_file_to_repo(file_path: str, repo_name: str, arch: Arch): for ext in ['db', 'files']: file = os.path.join(repo_dir, f'{repo_name}.{ext}') if os.path.exists(file + '.tar.xz'): - os.unlink(file) + remove_file(file) shutil.copyfile(file + '.tar.xz', file) old = file + '.tar.xz.old' if os.path.exists(old): - os.unlink(old) + remove_file(old) def strip_compression_extension(filename: str):