Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/goal.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ TDNFSolv(
BAIL_ON_TDNF_ERROR(dwError);
}

transaction_order(pTrans, 0);
if (pTdnf->pConf->ppszProtectedPkgs) {
/* catch protected obsoleted packages, and double check for removals */
dwError = TDNFSolvCheckProtectPkgsInTrans(pTdnf, pTrans, pTdnf->pSack->pPool);
Expand Down
21 changes: 21 additions & 0 deletions pytests/repo/tdnf-test-prein-base.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Summary: Test package - prein ordering base dependency
Name: tdnf-test-prein-base
Version: 1.0
Release: 1
Vendor: VMware, Inc.
Distribution: Photon
License: VMware
Url: http://www.vmware.com
Group: Applications/tdnftest

%description
Base package required by tdnf-test-prein-dep-a to give it more graph
weight than tdnf-test-prein-dep-b for transaction ordering tests.

%prep
%build
%install
%files
%changelog
* Fri Aug 21 2026 tdnf team 1.0-1
- Initial package
27 changes: 27 additions & 0 deletions pytests/repo/tdnf-test-prein-consumer.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Summary: Test package - prein ordering regression, consumer
Name: tdnf-test-prein-consumer
Version: 1.0
Release: 1
Vendor: VMware, Inc.
Distribution: Photon
License: VMware
Url: http://www.vmware.com
Group: Applications/tdnftest
Requires(pre): tdnf-test-prein-cap

%description
Consumer of tdnf-test-prein-cap via Requires(pre). The %pre scriptlet
ends with a never-taken if branch to verify POSIX sh exit-code semantics.

%pre
if [ "%{name}" = "not-this-name" ]; then
echo "unreachable"
fi

%prep
%build
%install
%files
%changelog
* Fri Aug 21 2026 tdnf team 1.0-1
- Initial package
24 changes: 24 additions & 0 deletions pytests/repo/tdnf-test-prein-dep-a.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Summary: Test package - prein ordering regression, provider A
Name: tdnf-test-prein-dep-a
Version: 1.0
Release: 1
Vendor: VMware, Inc.
Distribution: Photon
License: VMware
Url: http://www.vmware.com
Group: Applications/tdnftest
Provides: tdnf-test-prein-cap
Requires: tdnf-test-prein-base

%description
Provider A of tdnf-test-prein-cap. Requires tdnf-test-prein-base to gain
enough graph weight that transaction_order() consistently places it right
before the consumer (and after dep-b) in the install sequence.

%prep
%build
%install
%files
%changelog
* Fri Aug 21 2026 tdnf team 1.0-1
- Initial package
22 changes: 22 additions & 0 deletions pytests/repo/tdnf-test-prein-dep-b.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Summary: Test package - prein ordering regression, provider B
Name: tdnf-test-prein-dep-b
Version: 1.0
Release: 1
Vendor: VMware, Inc.
Distribution: Photon
License: VMware
Url: http://www.vmware.com
Group: Applications/tdnftest
Provides: tdnf-test-prein-cap

%description
Provider B of tdnf-test-prein-cap. No dependencies, giving it less graph
weight than dep-a so transaction_order() consistently places it earlier.

%prep
%build
%install
%files
%changelog
* Fri Aug 21 2026 tdnf team 1.0-1
- Initial package
60 changes: 60 additions & 0 deletions pytests/tests/test_transaction_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#
# Copyright (C) 2026 VMware, Inc. All Rights Reserved.
#
# Licensed under the GNU General Public License v2 (the "License");
# you may not use this file except in compliance with the License. The terms
# of the License are located in the COPYING file of this distribution.
#

import pytest

PREIN_BASE = "tdnf-test-prein-base"
PREIN_DEP_A = "tdnf-test-prein-dep-a"
PREIN_DEP_B = "tdnf-test-prein-dep-b"
PREIN_CONSUMER = "tdnf-test-prein-consumer"
PREIN_PKGS = [PREIN_BASE, PREIN_DEP_A, PREIN_DEP_B, PREIN_CONSUMER]


@pytest.fixture(scope="function", autouse=True)
def cleanup_prein_packages(utils):
utils.run(["tdnf", "remove", "-y"] + PREIN_PKGS)
yield
utils.run(["tdnf", "remove", "-y"] + PREIN_PKGS)


def _install_and_get_order(utils, pkgs):
ret = utils.run(["tdnf", "install", "-y", "--nogpgcheck"] + pkgs)
assert ret["retval"] == 0, "tdnf install failed (retval={}):\n{}".format(
ret["retval"], "\n".join(ret["stdout"] + ret["stderr"])
)
return [line for line in ret["stdout"] if line.startswith("Installing/Updating:")]


def _remove_prein_packages(utils):
ret = utils.run(["tdnf", "remove", "-y"] + PREIN_PKGS)
assert ret["retval"] == 0, "tdnf remove failed (retval={}):\n{}".format(
ret["retval"], "\n".join(ret["stdout"] + ret["stderr"])
)


# Regression test for transaction_order() fix in client/goal.c:
# without the fix, solver_create_transaction() leaves pTrans->steps in
# CLI-argument order; rpmtsOrder() then picks whichever Requires(pre)
# provider appears closest to the consumer as the ordering anchor, making
# the install sequence depend on CLI argument order.
def test_prein_install_order_is_deterministic(utils):
order_a_first = _install_and_get_order(
utils, [PREIN_DEP_A, PREIN_DEP_B, PREIN_CONSUMER]
)

_remove_prein_packages(utils)

order_b_first = _install_and_get_order(
utils, [PREIN_DEP_B, PREIN_DEP_A, PREIN_CONSUMER]
)

assert order_a_first == order_b_first, (
"Install order differed with different CLI argument order -- "
"transaction_order() may not be called after solver_create_transaction().\n"
"dep-a first: {}\ndep-b first: {}".format(order_a_first, order_b_first)
)
Loading