Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add history rollback command and transaction merging #1558

Merged
merged 4 commits into from
Jul 2, 2024

Conversation

kontura
Copy link
Contributor

@kontura kontura commented Jun 24, 2024

Merging is used to revert multiple transactions to achieve a rollback.
It includes extensive unit tests for merging various combinations of actions.

@kontura
Copy link
Contributor Author

kontura commented Jun 24, 2024

Tests update: rpm-software-management/ci-dnf-stack#1515

@evan-goode
Copy link
Member

Basic functionality looks good! I'll do a code review tomorrow.

Copy link
Member

@evan-goode evan-goode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this some more and it works well. It's great to have so many test cases in test_transaction_merge.cpp.

void run() override;

std::unique_ptr<TransactionSpecArguments> transaction_specs{nullptr};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making these private

transaction_item_action_is_inbound(previous_replay->second.action)) ||
(transaction_item_action_is_outbound(package_replay.action) &&
transaction_item_action_is_outbound(previous_replay->second.action))) {
// When both actions for nevra are inbound (REINSTALL excluded) or outbound use newer one and log it/warninging?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warninging typo?

insert_or_append(na_to_installed_nevras, name_arch, package_replay.nevra);
} else {
// Not installonly, keep only the latests action
nevra_to_package_replay.erase(na_to_installed_nevras[name_arch][0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: latests

transaction_item_action_to_string(previous_replay->second.action)));
nevra_to_package_replay[package_replay.nevra] = package_replay;
} else {
// Actions cancel out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true if both the current and previous replay are strictly either inbound or outbound, but does not necessarily hold if a replay is neither inbound nor outbound. I see that REASON_CHANGE and REINSTALL are handled above, but maybe it would be more defensive to explicitly check

(transaction_item_action_is_inbound(package_replay.action) &&
transaction_item_action_is_outbound(previous_replay->second.action)) ||
(transaction_item_action_is_outbound(package_replay.action) &&
transaction_item_action_is_inbound(previous_replay->second.action))

here and include an else branch for any other edge cases, for example, if some new TransactionItemAction is added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I will throw an exception in the new else block since it hard to foresee what could the new item action do.


auto previous_replay = nevra_to_package_replay.find(package_replay.nevra);

// When the previous action is REASON_CHANGE or REINSTALL override it (act as if its not there),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this comment be on the else branch? Since this branch runs when the previous is neither REASON_CHANGE nor REINSTALL

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, I meant the comment as an explanation for the if condition.
I tried moving the comment to else branch now and to me it felt more confusing.

Though you are right, it is talking about when the else branch is taken.

// the package isn't installed at the beginning other actions cannot be applied.
nevra_to_package_replay[package_replay.nevra] = package_replay;
if (package_replay.action != TransactionItemAction::INSTALL) {
// If some other version of this name_arch isn't removed in this transaction its an invalid transaction merge
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: its

namespace libdnf5::transaction {

// Merge a vector of transactions replays.
// Order matters when merging transacitons, we perfer the latest transaction actions (actions from TransactionReplays later in the vector).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: transacitons, perfer

This will be used in transaction merging.
It will be used by goal in `resolve_reverted_transactions(...)`.
The order is: first revert all specified transactions and then merge
them together.
@evan-goode
Copy link
Member

Thanks! Since the CI is failing due to librepo 1.18 not being available, I will run the tests locally and merge when they finish.

@evan-goode
Copy link
Member

Tests passing!

@evan-goode evan-goode added this pull request to the merge queue Jul 2, 2024
Merged via the queue into rpm-software-management:main with commit c4d5bbf Jul 2, 2024
1 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants