Py_RETURN_NONE;
}
+static PyObject* Transaction_download(TransactionObject* self) {
+ int r = pakfire_transaction_download(self->transaction);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
static Py_ssize_t Transaction_len(TransactionObject* self) {
return pakfire_transaction_count(self->transaction);
}
static struct PyMethodDef Transaction_methods[] = {
+ {
+ "download",
+ (PyCFunction)Transaction_download,
+ METH_NOARGS,
+ NULL,
+ },
{
"dump",
(PyCFunction)Transaction_dump,
METH_NOARGS,
- NULL
+ NULL,
},
{
"run",
PAKFIRE_PKG_DUMP_LONG = 1 << 1,
};
+#ifdef PAKFIRE_PRIVATE
+
+#include <solv/repo.h>
+
+int pakfire_package_is_in_repo(PakfirePackage pkg, Repo* repo);
+
+#endif
+
#endif /* PAKFIRE_PACKAGE_H */
Repo* pakfire_repo_get_repo(PakfireRepo repo);
Repodata* pakfire_repo_get_repodata(PakfireRepo repo);
+int pakfire_repo_download_packages(PakfireRepo repo, PakfirePackageList packages);
+
#endif
#endif /* PAKFIRE_REPO_H */
int pakfire_transaction_run(PakfireTransaction transaction);
+int pakfire_transaction_download(PakfireTransaction transaction);
+
#ifdef PAKFIRE_PRIVATE
Transaction* pakfire_transaction_get_transaction(PakfireTransaction transaction);
# transaction
pakfire_transaction_count;
pakfire_transaction_create;
+ pakfire_transaction_download;
pakfire_transaction_dump;
pakfire_transaction_get_packages;
pakfire_transaction_get_step;
#############################################################################*/
#include <assert.h>
+#include <linux/limits.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
pakfire_package_set_relationlist(pkg, SOLVABLE_ENHANCES, relationlist, 0);
}
+/*
+ Fast-path function to check if a package is in a certain repository
+*/
+int pakfire_package_is_in_repo(PakfirePackage pkg, Repo* repo) {
+ Solvable* s = get_solvable(pkg);
+
+ return s->repo == repo;
+}
+
PAKFIRE_EXPORT PakfireRepo pakfire_package_get_repo(PakfirePackage pkg) {
if (!pkg->repo) {
Solvable* s = get_solvable(pkg);
}
PAKFIRE_EXPORT char* pakfire_package_get_cache_path(PakfirePackage pkg) {
- char buffer[STRING_SIZE] = "";
+ char path[PATH_MAX];
const char* filename = pakfire_package_get_filename(pkg);
const char* checksum = pakfire_package_get_checksum(pkg);
if (strlen(checksum) < 3)
return NULL;
- snprintf(buffer, sizeof(buffer), "%c%c/%s/%s", checksum[0], checksum[1],
+ snprintf(path, sizeof(path) - 1, "%c%c/%s/%s", checksum[0], checksum[1],
checksum + 2, filename);
- return pakfire_make_cache_path(pkg->pakfire, buffer);
+ return pakfire_make_cache_path(pkg->pakfire, path);
}
PAKFIRE_EXPORT PakfireArchive pakfire_package_get_archive(PakfirePackage pkg) {
#include <pakfire/errno.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
+#include <pakfire/packagelist.h>
#include <pakfire/pakfire.h>
#include <pakfire/private.h>
#include <pakfire/repo.h>
// Refresh metadata
return pakfire_repo_refresh_metadata(repo, force);
}
+
+int pakfire_repo_download_packages(PakfireRepo repo, PakfirePackageList packages) {
+ int r;
+
+ struct pakfire_downloader* downloader = pakfire_repo_downloader(repo);
+ if (!downloader)
+ return 1;
+
+ const size_t num_packages = pakfire_packagelist_count(packages);
+
+ for (unsigned int i = 0; i < num_packages; i++) {
+ PakfirePackage pkg = pakfire_packagelist_get(packages, i);
+
+ // Skip packages that are not in this repository
+ if (!pakfire_package_is_in_repo(pkg, repo->repo)) {
+ pakfire_package_unref(pkg);
+ continue;
+ }
+
+ char* cache_path = pakfire_package_get_cache_path(pkg);
+
+ // Add transfer to downloader
+ r = pakfire_downloader_add_transfer(downloader,
+ pakfire_package_get_filename(pkg), cache_path);
+ if (r) {
+ pakfire_package_unref(pkg);
+ free(cache_path);
+ goto ERROR;
+ }
+ }
+
+ // Run the download
+ r = pakfire_downloader_run(downloader);
+
+ERROR:
+ pakfire_downloader_unref(downloader);
+
+ return r;
+}
return r;
}
+
+PAKFIRE_EXPORT int pakfire_transaction_download(PakfireTransaction transaction) {
+ /*
+ XXX TODO
+ This is not a very pretty solution, because we have to run a downloader
+ for each repository. It would be better to add all downloads to one downloader.
+ */
+ int r;
+
+ PakfirePackageList packages = pakfire_packagelist_create(transaction->pakfire);
+ if (!packages)
+ return 1;
+
+ // Add all packages that need to be downloaded
+ for (unsigned int i = 0; i < transaction->num_steps; i++) {
+ PakfireStep step = transaction->steps[i];
+
+ // Skip all steps that do not require a download
+ if (!pakfire_step_needs_download(step))
+ continue;
+
+ // Fetch the package
+ PakfirePackage pkg = pakfire_step_get_package(step);
+
+ // Add it to the list
+ pakfire_packagelist_push(packages, pkg);
+
+ pakfire_package_unref(pkg);
+ }
+
+ // If the list is empty, we do not need to continue
+ if (pakfire_packagelist_count(packages) == 0) {
+ r = 0;
+ goto ERROR;
+ }
+
+ Pool* pool = pakfire_get_solv_pool(transaction->pakfire);
+ Repo* repo;
+ int i;
+
+ FOR_REPOS(i, repo) {
+ PakfireRepo _repo = pakfire_repo_create_from_repo(transaction->pakfire, repo);
+
+ r = pakfire_repo_download_packages(_repo, packages);
+ pakfire_repo_unref(_repo);
+
+ if (r)
+ goto ERROR;
+ }
+
+ // Success
+ r = 0;
+
+ERROR:
+ if (packages)
+ pakfire_packagelist_unref(packages);
+
+ return r;
+}
from . import base
from . import cgroups
from . import config
-from . import downloaders
from . import logger
from . import packages
from . import repository
self.log.info(t)
# Download transaction
- d = downloaders.TransactionDownloader(self.pakfire, transaction)
- d.download()
+ transaction.download()
# Run the transaction
transaction.run()