diff --git a/0020-history-DB-Add-persistence-column.patch b/0020-history-DB-Add-persistence-column.patch new file mode 100644 index 0000000..c8c298d --- /dev/null +++ b/0020-history-DB-Add-persistence-column.patch @@ -0,0 +1,227 @@ +From 08537bba12f1a127a99bed87fe83032466e597dc Mon Sep 17 00:00:00 2001 +From: Evan Goode +Date: Thu, 15 May 2025 20:44:18 +0000 +Subject: [PATCH 1/3] history DB: Add "persistence" column + +For https://github.com/rpm-software-management/dnf/issues/2196. +The `persistence` column is a TransactionPersistence enum, currently it +can either be UNKNOWN, PERSIST, or TRANSIENT. +--- + libdnf/transaction/Swdb.cpp | 8 ++++++++ + libdnf/transaction/Swdb.hpp | 1 + + libdnf/transaction/Transaction.cpp | 2 ++ + libdnf/transaction/Transaction.hpp | 3 +++ + libdnf/transaction/Transformer.cpp | 7 +++++++ + libdnf/transaction/Transformer.hpp | 2 +- + libdnf/transaction/Types.hpp | 6 ++++++ + libdnf/transaction/private/Transaction.cpp | 8 ++++++-- + libdnf/transaction/private/Transaction.hpp | 1 + + libdnf/transaction/sql/migrate_tables_1_3.sql | 9 +++++++++ + 10 files changed, 44 insertions(+), 3 deletions(-) + create mode 100644 libdnf/transaction/sql/migrate_tables_1_3.sql + +diff --git a/libdnf/transaction/Swdb.cpp b/libdnf/transaction/Swdb.cpp +index 9626f732..3c7f84ce 100644 +--- a/libdnf/transaction/Swdb.cpp ++++ b/libdnf/transaction/Swdb.cpp +@@ -385,6 +385,14 @@ Swdb::setReleasever(std::string value) + transactionInProgress->setReleasever(value); + } + ++void ++Swdb::setPersistence(TransactionPersistence persistence) ++{ ++ if (!transactionInProgress) { ++ throw std::logic_error(_("Not in progress")); ++ } ++ transactionInProgress->setPersistence(persistence); ++} + + void + Swdb::addConsoleOutputLine(int fileDescriptor, std::string line) +diff --git a/libdnf/transaction/Swdb.hpp b/libdnf/transaction/Swdb.hpp +index 5b2342c8..9ae6b52d 100644 +--- a/libdnf/transaction/Swdb.hpp ++++ b/libdnf/transaction/Swdb.hpp +@@ -114,6 +114,7 @@ public: + + // misc + void setReleasever(std::string value); ++ void setPersistence(TransactionPersistence value); + void addConsoleOutputLine(int fileDescriptor, std::string line); + + /** +diff --git a/libdnf/transaction/Transaction.cpp b/libdnf/transaction/Transaction.cpp +index 208f6763..3aac1cb9 100644 +--- a/libdnf/transaction/Transaction.cpp ++++ b/libdnf/transaction/Transaction.cpp +@@ -82,6 +82,7 @@ Transaction::dbSelect(int64_t pk) + " releasever, " + " user_id, " + " cmdline, " ++ " persistence, " + " state, " + " comment " + "FROM " +@@ -100,6 +101,7 @@ Transaction::dbSelect(int64_t pk) + releasever = query.get< std::string >("releasever"); + userId = query.get< uint32_t >("user_id"); + cmdline = query.get< std::string >("cmdline"); ++ persistence = static_cast(query.get("persistence")); + state = static_cast< TransactionState >(query.get< int >("state")); + comment = query.get< std::string >("comment"); + } +diff --git a/libdnf/transaction/Transaction.hpp b/libdnf/transaction/Transaction.hpp +index a4aba8f3..58f4e4cd 100644 +--- a/libdnf/transaction/Transaction.hpp ++++ b/libdnf/transaction/Transaction.hpp +@@ -55,6 +55,8 @@ public: + const std::string &getReleasever() const noexcept { return releasever; } + uint32_t getUserId() const noexcept { return userId; } + const std::string &getCmdline() const noexcept { return cmdline; } ++ TransactionPersistence getPersistence() const noexcept { return persistence; } ++ + TransactionState getState() const noexcept { return state; } + const std::string &getComment() const noexcept { return comment; } + +@@ -79,6 +81,7 @@ protected: + std::string releasever; + uint32_t userId = 0; + std::string cmdline; ++ TransactionPersistence persistence = TransactionPersistence::UNKNOWN; + TransactionState state = TransactionState::UNKNOWN; + std::string comment; + }; +diff --git a/libdnf/transaction/Transformer.cpp b/libdnf/transaction/Transformer.cpp +index ef4c0669..ba1b882d 100644 +--- a/libdnf/transaction/Transformer.cpp ++++ b/libdnf/transaction/Transformer.cpp +@@ -53,6 +53,10 @@ static const char * const sql_migrate_tables_1_2 = + #include "sql/migrate_tables_1_2.sql" + ; + ++static const char * const sql_migrate_tables_1_3 = ++#include "sql/migrate_tables_1_3.sql" ++ ; ++ + void + Transformer::createDatabase(SQLite3Ptr conn) + { +@@ -70,6 +74,9 @@ Transformer::migrateSchema(SQLite3Ptr conn) + + if (schemaVersion == "1.1") { + conn->exec(sql_migrate_tables_1_2); ++ conn->exec(sql_migrate_tables_1_3); ++ } else if (schemaVersion == "1.2") { ++ conn->exec(sql_migrate_tables_1_3); + } + } + else { +diff --git a/libdnf/transaction/Transformer.hpp b/libdnf/transaction/Transformer.hpp +index 87c0e1f4..a99ea066 100644 +--- a/libdnf/transaction/Transformer.hpp ++++ b/libdnf/transaction/Transformer.hpp +@@ -60,7 +60,7 @@ public: + static void migrateSchema(SQLite3Ptr conn); + + static TransactionItemReason getReason(const std::string &reason); +- static const char *getVersion() noexcept { return "1.2"; } ++ static const char *getVersion() noexcept { return "1.3"; } + + protected: + void transformTrans(SQLite3Ptr swdb, SQLite3Ptr history); +diff --git a/libdnf/transaction/Types.hpp b/libdnf/transaction/Types.hpp +index 0003bbb7..574ed085 100644 +--- a/libdnf/transaction/Types.hpp ++++ b/libdnf/transaction/Types.hpp +@@ -56,6 +56,12 @@ enum class TransactionItemAction : int { + REASON_CHANGE = 11 // a package was kept on the system but it's reason has changed + }; + ++enum class TransactionPersistence : int { ++ UNKNOWN = 0, ++ PERSIST = 1, ++ TRANSIENT = 2, ++}; ++ + } // namespace libdnf + /* + Install +diff --git a/libdnf/transaction/private/Transaction.cpp b/libdnf/transaction/private/Transaction.cpp +index 088d6ba9..0131cbb8 100644 +--- a/libdnf/transaction/private/Transaction.cpp ++++ b/libdnf/transaction/private/Transaction.cpp +@@ -76,12 +76,13 @@ swdb_private::Transaction::dbInsert() + " releasever, " + " user_id, " + " cmdline, " ++ " persistence, " + " state, " + " comment, " + " id " + " ) " + "VALUES " +- " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; ++ " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + SQLite3::Statement query(*conn.get(), sql); + query.bindv(getDtBegin(), + getDtEnd(), +@@ -90,10 +91,11 @@ swdb_private::Transaction::dbInsert() + getReleasever(), + getUserId(), + getCmdline(), ++ static_cast(getPersistence()), + static_cast< int >(getState()), + getComment()); + if (getId() > 0) { +- query.bind(9, getId()); ++ query.bind(10, getId()); + } + query.step(); + setId(conn->lastInsertRowID()); +@@ -138,6 +140,7 @@ swdb_private::Transaction::dbUpdate() + " releasever=?, " + " user_id=?, " + " cmdline=?, " ++ " persistence=?, " + " state=?, " + " comment=? " + "WHERE " +@@ -150,6 +153,7 @@ swdb_private::Transaction::dbUpdate() + getReleasever(), + getUserId(), + getCmdline(), ++ static_cast(getPersistence()), + static_cast< int >(getState()), + getComment(), + getId()); +diff --git a/libdnf/transaction/private/Transaction.hpp b/libdnf/transaction/private/Transaction.hpp +index 9e0d6848..dd5ba0a0 100644 +--- a/libdnf/transaction/private/Transaction.hpp ++++ b/libdnf/transaction/private/Transaction.hpp +@@ -42,6 +42,7 @@ public: + void setReleasever(const std::string &value) { releasever = value; } + void setUserId(uint32_t value) { userId = value; } + void setCmdline(const std::string &value) { cmdline = value; } ++ void setPersistence(TransactionPersistence value) { persistence = value; } + void setState(TransactionState value) { state = value; } + void setComment(const std::string &value) { comment = value; } + +diff --git a/libdnf/transaction/sql/migrate_tables_1_3.sql b/libdnf/transaction/sql/migrate_tables_1_3.sql +new file mode 100644 +index 00000000..6901874e +--- /dev/null ++++ b/libdnf/transaction/sql/migrate_tables_1_3.sql +@@ -0,0 +1,9 @@ ++R"**( ++BEGIN TRANSACTION; ++ ALTER TABLE trans ++ ADD persistence INTEGER DEFAULT 0; ++ UPDATE config ++ SET value = '1.3' ++ WHERE key = 'version'; ++COMMIT; ++)**" +-- +2.49.0 + diff --git a/0021-MergedTransaction-listPersistences.patch b/0021-MergedTransaction-listPersistences.patch new file mode 100644 index 0000000..0bd4235 --- /dev/null +++ b/0021-MergedTransaction-listPersistences.patch @@ -0,0 +1,46 @@ +From 455712f7f852eb808c12aa20106d2a921e90a9dd Mon Sep 17 00:00:00 2001 +From: Evan Goode +Date: Mon, 19 May 2025 22:37:36 +0000 +Subject: [PATCH 2/3] MergedTransaction::listPersistences + +--- + libdnf/transaction/MergedTransaction.cpp | 10 ++++++++++ + libdnf/transaction/MergedTransaction.hpp | 1 + + 2 files changed, 11 insertions(+) + +diff --git a/libdnf/transaction/MergedTransaction.cpp b/libdnf/transaction/MergedTransaction.cpp +index 75d2c1e7..8f556c02 100644 +--- a/libdnf/transaction/MergedTransaction.cpp ++++ b/libdnf/transaction/MergedTransaction.cpp +@@ -97,6 +97,16 @@ MergedTransaction::listCmdlines() const + return cmdLines; + } + ++std::vector< TransactionPersistence > ++MergedTransaction::listPersistences() const ++{ ++ std::vector< TransactionPersistence > persistences; ++ for (auto t : transactions) { ++ persistences.push_back(t->getPersistence()); ++ } ++ return persistences; ++} ++ + std::vector< TransactionState > + MergedTransaction::listStates() const + { +diff --git a/libdnf/transaction/MergedTransaction.hpp b/libdnf/transaction/MergedTransaction.hpp +index 50212159..5ef9fb30 100644 +--- a/libdnf/transaction/MergedTransaction.hpp ++++ b/libdnf/transaction/MergedTransaction.hpp +@@ -47,6 +47,7 @@ public: + std::vector< int64_t > listIds() const; + std::vector< uint32_t > listUserIds() const; + std::vector< std::string > listCmdlines() const; ++ std::vector< TransactionPersistence > listPersistences() const; + std::vector< TransactionState > listStates() const; + std::vector< std::string > listReleasevers() const; + std::vector< std::string > listComments() const; +-- +2.49.0 + diff --git a/0022-conf-Add-usr_drift_protected_paths.patch b/0022-conf-Add-usr_drift_protected_paths.patch new file mode 100644 index 0000000..4c22dea --- /dev/null +++ b/0022-conf-Add-usr_drift_protected_paths.patch @@ -0,0 +1,66 @@ +From 6de9945e1983cd27f79980fd1a6e0a92210e7f7a Mon Sep 17 00:00:00 2001 +From: Evan Goode +Date: Wed, 28 May 2025 20:39:20 +0000 +Subject: [PATCH 3/3] conf: Add usr_drift_protected_paths + +Adds the `usr_drift_protected_paths` configuration option which can be +configured by adding .conf files to the drop-in directory +/etc/dnf/usr-drift-protected-paths.d, similar to /etc/dnf/protected.d. +Distributions will be able to add paths that are known to cause problems +when their contents drift with respect to /usr, e.g. /etc/pam.d. + +For https://github.com/rpm-software-management/dnf/issues/2199. +--- + libdnf/conf/ConfigMain.cpp | 9 +++++++++ + libdnf/conf/ConfigMain.hpp | 1 + + 2 files changed, 10 insertions(+) + +diff --git a/libdnf/conf/ConfigMain.cpp b/libdnf/conf/ConfigMain.cpp +index cee6e2cf..27c5c687 100644 +--- a/libdnf/conf/ConfigMain.cpp ++++ b/libdnf/conf/ConfigMain.cpp +@@ -292,6 +292,8 @@ class ConfigMain::Impl { + OptionBool countme{false}; + OptionBool protect_running_kernel{true}; + ++ OptionStringList usr_drift_protected_paths{resolveGlobs("glob:/etc/dnf/usr-drift-protected-paths.d/*.conf")}; ++ + // Repo main config + + OptionNumber retries{10}; +@@ -457,6 +459,12 @@ ConfigMain::Impl::Impl(Config & owner) + owner.optBinds().add("countme", countme); + owner.optBinds().add("protect_running_kernel", protect_running_kernel); + owner.optBinds().add("persistence", persistence); ++ owner.optBinds().add("usr_drift_protected_paths", usr_drift_protected_paths, ++ [&](Option::Priority priority, const std::string & value){ ++ if (priority >= usr_drift_protected_paths.getPriority()) ++ usr_drift_protected_paths.set(priority, resolveGlobs(value)); ++ }, nullptr, false ++ ); + + // Repo main config + +@@ -600,6 +608,7 @@ OptionString & ConfigMain::comment() { return pImpl->comment; } + OptionBool & ConfigMain::downloadonly() { return pImpl->downloadonly; } + OptionBool & ConfigMain::ignorearch() { return pImpl->ignorearch; } + OptionEnum & ConfigMain::persistence() { return pImpl->persistence; } ++OptionStringList & ConfigMain::usr_drift_protected_paths() { return pImpl->usr_drift_protected_paths; } + + OptionString & ConfigMain::module_platform_id() { return pImpl->module_platform_id; } + OptionBool & ConfigMain::module_stream_switch() { return pImpl->module_stream_switch; } +diff --git a/libdnf/conf/ConfigMain.hpp b/libdnf/conf/ConfigMain.hpp +index 1ef28e7b..96d965af 100644 +--- a/libdnf/conf/ConfigMain.hpp ++++ b/libdnf/conf/ConfigMain.hpp +@@ -124,6 +124,7 @@ public: + OptionBool & downloadonly(); + OptionBool & ignorearch(); + OptionEnum & persistence(); ++ OptionStringList & usr_drift_protected_paths(); + + OptionString & module_platform_id(); + OptionBool & module_stream_switch(); +-- +2.49.0 + diff --git a/libdnf.spec b/libdnf.spec index c95eaf6..c74c115 100644 --- a/libdnf.spec +++ b/libdnf.spec @@ -58,7 +58,7 @@ Name: libdnf Version: %{libdnf_major_version}.%{libdnf_minor_version}.%{libdnf_micro_version} -Release: 14%{?dist} +Release: 15%{?dist} Summary: Library providing simplified C and Python API to libsolv License: LGPLv2+ URL: https://github.com/rpm-software-management/libdnf @@ -82,6 +82,9 @@ Patch16: 0016-repo-Don-t-try-to-perform-labeling-if-SELinux-is-dis.patch Patch17: 0017-Add-persistence-config-option.patch Patch18: 0018-conf-Improve-granularity-of-ConfigParser-exceptions.patch Patch19: 0019-module-Warn-if-module-config-file-is-inaccessible.patch +Patch20: 0020-history-DB-Add-persistence-column.patch +Patch21: 0021-MergedTransaction-listPersistences.patch +Patch22: 0022-conf-Add-usr_drift_protected_paths.patch BuildRequires: cmake @@ -331,6 +334,10 @@ popd %endif %changelog +* Thu Jun 26 2025 Evan Goode - 0.69.0-15 +- history DB: Add "persistence" column (RHEL-100623) +- conf: Add bootc_unsafe_paths (RHEL-100622) + * Wed Mar 12 2025 Marek Blaha - 0.69.0-14 - module: Warn if module config file is inaccessible (RHEL-62833)