libdnf5 (python): `TransactionItem.get_reason_change_group_id()` is always empty?
Hi, I have the following code snippet which looks up some groups/packages; stuffs them into a transaction and then needs the reason for installation:
#!/usr/bin/python3
import sys
import libdnf5 as dnf5
from libdnf5.base import GoalProblem_NO_PROBLEM as NO_PROBLEM
base = dnf5.base.Base()
conf = base.get_config()
conf.fastestmirror = True
conf.install_weak_deps = True
conf.zchunk = False
conf.config_file_path = "/dev/null"
conf.cachedir = "/tmp/dnf-test"
base.setup()
repo_sack = base.get_repo_sack()
repo = repo_sack.create_repo("my-repo")
repo_conf = repo.get_config()
repo_conf.name = "fedora"
repo_conf.metalink = (
"https://mirrors.fedoraproject.org/metalink?repo=fedora-38&arch=x86_64"
)
repo_sack.update_and_load_enabled_repos(load_system=False)
rpm_sack = base.get_rpm_package_sack()
rpm_sack.clear_user_excludes()
goal = dnf5.base.Goal(base)
goal.reset()
settings = dnf5.base.GoalJobSettings()
settings.group_with_name = True
for thing in sys.argv[1:]:
goal.add_install(thing, settings)
transaction = goal.resolve()
if transaction.get_problems() != NO_PROBLEM:
print("\n".join(transaction.get_resolve_logs_as_strings()))
raise SystemExit()
tis = [
ti
for ti in transaction.get_transaction_packages()
if dnf5.base.transaction.transaction_item_action_is_inbound(ti.get_action())
]
reasons = [
"NONE",
"DEPENDENCY",
"USER",
"CLEAN",
"WEAK_DEPENDENCY",
"GROUP",
"EXTERNAL_USER",
]
for ti in tis:
print(
ti.get_package().get_name(),
"--",
reasons[ti.get_reason()],
repr(ti.get_reason_change_group_id()),
)
Call with python3 script.py '@core'. The output is (abbreviated):
user@muja images € ./dnf5-test.py '@core'
sudo -- GROUP ''
curl -- GROUP ''
...
audit-libs -- DEPENDENCY ''
glibc -- DEPENDENCY ''
libselinux -- DEPENDENCY ''
openldap -- DEPENDENCY ''
openssl-libs -- DEPENDENCY ''
pam-libs -- DEPENDENCY ''
zlib -- DEPENDENCY ''
dhcp-common -- DEPENDENCY ''
...
I would have expected the transaction items that have a get_reason() of GROUP to have a filled in get_reason_change_group_id(). Perhaps I have set up base incorrectly?
Similary, this has the same behavior in dnf(4):
#!/usr/bin/env python
import sys
import dnf
base = dnf.Base()
conf = base.conf
conf.cachedir = "/tmp/my_cache_dir"
conf.substitutions["releasever"] = "38"
conf.substitutions["basearch"] = "x86_64"
base.repos.add_new_repo(
"my-repo",
conf,
baseurl=[
"http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/os/"
],
)
base.fill_sack()
base.install_specs(sys.argv[1:])
base.resolve()
tis = [
ti
for ti in base.transaction
if ti.action in dnf.transaction.FORWARD_ACTIONS
]
for ti in tis:
print(ti, ti.reason, ti.get_group())
The field reason_change_group_id is currently utilized only by dnf5 mark group <groupid> <packageid> command to change the reason of an installed package to the group. In dnf5 it is not possible to mark a package as group-installed without specifying a group-id.
An example use-case could be as follows:
# dnf install rpm-build # installs rpm-build with reason USER
# dnf install @rpm-development-tools # rpm-build is part of rpm-development-tools but will stay on the system with USER reason
# dnf mark group rpm-development-tools rpm-build # will change the reason of rpm-build to GROUP. Here you will see reason_change_group_id in the transaction item set.
The field
reason_change_group_idis currently utilized only bydnf5 mark group <groupid> <packageid>command to change the reason of an installed package to thegroup. In dnf5 it is not possible to mark a package asgroup-installedwithout specifying a group-id. An example use-case could be as follows:# dnf install rpm-build # installs rpm-build with reason USER # dnf install @rpm-development-tools # rpm-build is part of rpm-development-tools but will stay on the system with USER reason # dnf mark group rpm-development-tools rpm-build # will change the reason of rpm-build to GROUP. Here you will see reason_change_group_id in the transaction item set.
Understood. I'm looking for a way to ask DNF 'I added install @core to my goal' to then get the packages that should be marked as group installed to @core. It seems DNF fills this in in during the resolve of the transaction: https://github.com/rpm-software-management/dnf5/blob/main/libdnf5/base/transaction.cpp#L435 (note: I am unfamiliar with libdnf!).
How does libdnf when doing an install know how to mark the packages? E.g. if I run the transaction it seems that the packages are marked correctly, I'd like to find that information without running the transaction.
My usecase is that I'm doing depsolving for a list of (user-requested) installs and excludes, resolving this to a set of RPMs, installing those through RPM. I then need to fix up the dnf state database after that. This works 'ok' so for user, weak, weak-dependency marked packages but for group I am unable to access which group things should belong to and so can't mark them correctly.