Skip to content

Commit c3c2b64

Browse files
m-blahakontura
authored andcommitted
dnf5: Reuse cached packages for offline and store transactions
Before downloading packages for an offline or store transaction, reuse packages already present in the cache (e.g., from dnf-automatic) to avoid re-downloading them unnecessarily. Signed-off-by: Marek Blaha <mblaha@redhat.com>
1 parent 7ab457d commit c3c2b64

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

dnf5/context.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <libdnf5/rpm/package_set.hpp>
4040
#include <libdnf5/rpm/rpm_signature.hpp>
4141
#include <libdnf5/transaction/offline.hpp>
42+
#include <libdnf5/transaction/transaction_item_action.hpp>
4243
#include <libdnf5/utils/bgettext/bgettext-lib.h>
4344
#include <libdnf5/utils/bgettext/bgettext-mark-domain.h>
4445
#include <libdnf5/utils/fs/file.hpp>
@@ -337,6 +338,37 @@ void Context::Impl::store_offline(libdnf5::base::Transaction & transaction) {
337338
state.write();
338339
}
339340

341+
/// Prepopulate the offline destdir with already-cached packages from the repo
342+
/// cache to avoid re-downloading them. Must be called before setting destdir,
343+
/// so that get_package_path() / is_available_locally() still resolve to the
344+
/// repo cache.
345+
static void prepopulate_offline_cache(
346+
libdnf5::base::Transaction & transaction, const std::filesystem::path & packages_dir) {
347+
bool packages_dir_created = false;
348+
for (auto & tspkg : transaction.get_transaction_packages()) {
349+
if (!libdnf5::transaction::transaction_item_action_is_inbound(tspkg.get_action())) {
350+
continue;
351+
}
352+
auto pkg = tspkg.get_package();
353+
if (pkg.get_repo()->get_type() == libdnf5::repo::Repo::Type::COMMANDLINE) {
354+
continue;
355+
}
356+
if (!pkg.is_available_locally()) {
357+
continue;
358+
}
359+
if (!packages_dir_created) {
360+
std::filesystem::create_directories(packages_dir);
361+
packages_dir_created = true;
362+
}
363+
auto cached_path = std::filesystem::path(pkg.get_package_path());
364+
auto dest_path = packages_dir / cached_path.filename();
365+
std::error_code ec;
366+
if (!std::filesystem::exists(dest_path, ec)) {
367+
std::filesystem::copy_file(cached_path, dest_path, ec);
368+
}
369+
}
370+
}
371+
340372
void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) {
341373
if (!transaction_store_path.empty()) {
342374
auto & config = base.get_config();
@@ -356,9 +388,10 @@ void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) {
356388
throw libdnf5::cli::AbortedByUserError();
357389
}
358390
}
391+
std::filesystem::create_directories(transaction_store_path);
392+
prepopulate_offline_cache(transaction, packages_location);
359393
auto & destdir_opt = config.get_destdir_option();
360394
destdir_opt.set(packages_location);
361-
std::filesystem::create_directories(transaction_store_path);
362395
// Override keepcache option because stored transaction packages should be always kept.
363396
// Following transactions should never remove them.
364397
auto & keepcache_opt = config.get_keepcache_option();
@@ -389,7 +422,9 @@ void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) {
389422
throw libdnf5::cli::AbortedByUserError();
390423
}
391424
}
392-
base.get_config().get_destdir_option().set(offline_destdir / "packages");
425+
const auto & packages_dir = offline_destdir / "packages";
426+
prepopulate_offline_cache(transaction, packages_dir);
427+
base.get_config().get_destdir_option().set(packages_dir);
393428
transaction.set_download_local_pkgs(true);
394429
}
395430

0 commit comments

Comments
 (0)