Merge pull request #22 from kiviktnm/fix-remove-chroot-virtual-pkgs

Fix removing virtual packages from chroots #7
This commit is contained in:
Kivi Kaitaniemi
2025-03-08 15:11:32 +02:00
committed by GitHub
3 changed files with 62 additions and 29 deletions
+35 -23
View File
@@ -58,7 +58,8 @@ decman.user_packages.append(
"python-wheel", "python-wheel",
], ],
git_url="https://github.com/kiviktnm/decman-pkgbuild.git", git_url="https://github.com/kiviktnm/decman-pkgbuild.git",
)) )
)
# Managing only packages with decman is not that interesting. # Managing only packages with decman is not that interesting.
# Decman also has really powerful ways of managing config files, scripts etc. # Decman also has really powerful ways of managing config files, scripts etc.
@@ -68,23 +69,25 @@ decman.user_packages.append(
# Define file content inline. # Define file content inline.
# Default text file encoding is utf-8 but it can be changed. # Default text file encoding is utf-8 but it can be changed.
decman.files["/etc/vconsole.conf"] = File(content="KEYMAP=us", decman.files["/etc/vconsole.conf"] = File(content="KEYMAP=us", encoding="utf-8")
encoding="utf-8")
# Include file content from another file, set the file owner and permissions. # Include file content from another file, set the file owner and permissions.
# The source_file is relative to the directory where the main decman source.py is located. # The source_file is relative to the directory where the main decman source.py is located.
# By default, the file group is set to the group of the owner, but it can be overridden with the group argument. # By default, the file group is set to the group of the owner, but it can be overridden with the group argument.
decman.files["/home/kk/.bin/user-script.sh"] = File( decman.files["/home/kk/.bin/user-script.sh"] = File(
source_file="files/user-script.sh", owner="kk", permissions=0o744) source_file="files/user-script.sh", owner="kk", permissions=0o744
)
# Non-text files such as images can also be managed. # Non-text files such as images can also be managed.
decman.files["/home/kk/.background.png"] = File( decman.files["/home/kk/.background.png"] = File(
source_file="files/i-dont-actually-exist.png", bin_file=True, owner="kk") source_file="files/i-dont-actually-exist.png", bin_file=True, owner="kk"
)
# If you need to install multiple files at once, use directories. # If you need to install multiple files at once, use directories.
# All files from the source directory will be copied recursively to the target. # All files from the source directory will be copied recursively to the target.
decman.directories["/home/kk/.config/app/"] = Directory( decman.directories["/home/kk/.config/app/"] = Directory(
source_directory="files/app-config", owner="kk") source_directory="files/app-config", owner="kk"
)
# Decman has built in support for managing systemd units as well. # Decman has built in support for managing systemd units as well.
# Decman will enable services declared here, and disable services removed from here. # Decman will enable services declared here, and disable services removed from here.
@@ -95,8 +98,9 @@ decman.enabled_systemd_units += ["NetworkManager.service"]
# You can manage units for users as well. # You can manage units for users as well.
# Ensure that previous user unit declarations aren't overwritten and they are initialized. # Ensure that previous user unit declarations aren't overwritten and they are initialized.
decman.enabled_systemd_user_units[ decman.enabled_systemd_user_units["kk"] = decman.enabled_systemd_user_units.get(
"kk"] = decman.enabled_systemd_user_units.get("kk", []) "kk", []
)
# Add user unit. # Add user unit.
decman.enabled_systemd_user_units["kk"].append("syncthing.service") decman.enabled_systemd_user_units["kk"].append("syncthing.service")
@@ -173,7 +177,6 @@ decman.config.number_of_packages_stored_in_cache = 3
# Create a child class of the decman.config.Commands class and override methods. # Create a child class of the decman.config.Commands class and override methods.
# These are the defaults. # These are the defaults.
class MyCommands(decman.config.Commands): class MyCommands(decman.config.Commands):
def list_pkgs(self) -> list[str]: def list_pkgs(self) -> list[str]:
return ["pacman", "-Qeq", "--color=never"] return ["pacman", "-Qeq", "--color=never"]
@@ -193,8 +196,7 @@ class MyCommands(decman.config.Commands):
return ["pacman", "-D", "--asexplicit"] + pkgs return ["pacman", "-D", "--asexplicit"] + pkgs
def install_deps(self, deps: list[str]) -> list[str]: def install_deps(self, deps: list[str]) -> list[str]:
return ["pacman", "-S", "--color=always", "--needed", "--asdeps" return ["pacman", "-S", "--color=always", "--needed", "--asdeps"] + deps
] + deps
def is_installable(self, pkg: str) -> list[str]: def is_installable(self, pkg: str) -> list[str]:
return ["pacman", "-Sddp", pkg] return ["pacman", "-Sddp", pkg]
@@ -217,8 +219,7 @@ class MyCommands(decman.config.Commands):
def disable_user_units(self, units: list[str], user: str) -> list[str]: def disable_user_units(self, units: list[str], user: str) -> list[str]:
return ["systemctl", "--user", "-M", f"{user}@", "disable"] + units return ["systemctl", "--user", "-M", f"{user}@", "disable"] + units
def compare_versions(self, installed_version: str, def compare_versions(self, installed_version: str, new_version: str) -> list[str]:
new_version: str) -> list[str]:
return ["vercmp", installed_version, new_version] return ["vercmp", installed_version, new_version]
def git_clone(self, repo: str, dest: str) -> list[str]: def git_clone(self, repo: str, dest: str) -> list[str]:
@@ -241,19 +242,31 @@ class MyCommands(decman.config.Commands):
def install_chroot_packages(self, chroot_dir: str, packages: list[str]): def install_chroot_packages(self, chroot_dir: str, packages: list[str]):
return [ return [
"arch-nspawn", chroot_dir, "pacman", "-S", "--needed", "arch-nspawn",
"--noconfirm" chroot_dir,
"pacman",
"-S",
"--needed",
"--noconfirm",
] + packages ] + packages
def resolve_real_name(self, chroot_dir: str, pkg: str) -> list[str]:
return [
"arch-nspawn",
chroot_dir,
"pacman",
"-Sddp",
"--print-format=%n",
pkg,
]
def remove_chroot_packages(self, chroot_dir: str, packages: list[str]): def remove_chroot_packages(self, chroot_dir: str, packages: list[str]):
return ["arch-nspawn", chroot_dir, "pacman", "-Rsu", "--noconfirm" return ["arch-nspawn", chroot_dir, "pacman", "-Rsu", "--noconfirm"] + packages
] + packages
def make_chroot_pkg(self, chroot_wd_dir: str, user: str, def make_chroot_pkg(
pkgfiles_to_install: list[str]) -> list[str]: self, chroot_wd_dir: str, user: str, pkgfiles_to_install: list[str]
makechrootpkg_cmd = [ ) -> list[str]:
"makechrootpkg", "-c", "-r", chroot_wd_dir, "-U", user makechrootpkg_cmd = ["makechrootpkg", "-c", "-r", chroot_wd_dir, "-U", user]
]
for pkgfile in pkgfiles_to_install: for pkgfile in pkgfiles_to_install:
makechrootpkg_cmd += ["-I", pkgfile] makechrootpkg_cmd += ["-I", pkgfile]
@@ -270,7 +283,6 @@ decman.config.commands = MyCommands()
class PikaurWrapperCommands(decman.config.Commands): class PikaurWrapperCommands(decman.config.Commands):
def list_pkgs(self) -> list[str]: def list_pkgs(self) -> list[str]:
return ["pikaur", "-Qeq"] return ["pikaur", "-Qeq"]
+13
View File
@@ -166,6 +166,19 @@ class Commands:
"--noconfirm", "--noconfirm",
] + packages ] + packages
def resolve_real_name(self, chroot_dir: str, pkg: str) -> list[str]:
"""
This command prints a real name of a package. For example, it prints the package which provides a virtual package.
"""
return [
"arch-nspawn",
chroot_dir,
"pacman",
"-Sddp",
"--print-format=%n",
pkg,
]
def remove_chroot_packages(self, chroot_dir: str, packages: list[str]): def remove_chroot_packages(self, chroot_dir: str, packages: list[str]):
""" """
Running this command removes the given packages from the given chroot. Running this command removes the given packages from the given chroot.
+10 -2
View File
@@ -984,12 +984,20 @@ class PackageBuilder:
l.print_info("Removing build dependencies from chroot.") l.print_info("Removing build dependencies from chroot.")
# FIX: If installed packages are virtual packages, removing them wont succeed.
if len(chroot_new_pacman_pkgs) != 0: if len(chroot_new_pacman_pkgs) != 0:
to_remove = [] to_remove = []
for p in chroot_new_pacman_pkgs: for p in chroot_new_pacman_pkgs:
if p not in self._pkgs_in_chroot: if p not in self._pkgs_in_chroot:
to_remove.append(strip_dependency(p)) real_pkgname = (
subprocess.run(
conf.commands.resolve_real_name(self.chroot_dir, p),
check=True,
stdout=subprocess.PIPE,
)
.stdout.decode()
.strip()
)
to_remove.append(real_pkgname)
subprocess.run( subprocess.run(
conf.commands.remove_chroot_packages(self.chroot_dir, to_remove), conf.commands.remove_chroot_packages(self.chroot_dir, to_remove),
check=True, check=True,