1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2013 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
24 #include <solv/transaction.h>
26 #include <pakfire/archive.h>
27 #include <pakfire/db.h>
28 #include <pakfire/downloader.h>
29 #include <pakfire/execute.h>
30 #include <pakfire/i18n.h>
31 #include <pakfire/logging.h>
32 #include <pakfire/package.h>
33 #include <pakfire/pakfire.h>
34 #include <pakfire/private.h>
35 #include <pakfire/repo.h>
36 #include <pakfire/transaction.h>
37 #include <pakfire/types.h>
38 #include <pakfire/ui.h>
39 #include <pakfire/util.h>
41 struct pakfire_transaction
{
45 Transaction
* transaction
;
47 PakfireArchive
* archives
;
48 PakfirePackage
* packages
;
52 static pakfire_step_type_t
pakfire_transaction_get_step_type(
53 struct pakfire_transaction
* transaction
, PakfirePackage pkg
) {
54 int type
= transaction_type(transaction
->transaction
, pakfire_package_id(pkg
),
55 SOLVER_TRANSACTION_SHOW_ACTIVE
|SOLVER_TRANSACTION_CHANGE_IS_REINSTALL
);
57 // Translate solver types into our own types
59 case SOLVER_TRANSACTION_INSTALL
:
60 case SOLVER_TRANSACTION_MULTIINSTALL
:
61 return PAKFIRE_STEP_INSTALL
;
63 case SOLVER_TRANSACTION_REINSTALL
:
64 case SOLVER_TRANSACTION_MULTIREINSTALL
:
65 return PAKFIRE_STEP_REINSTALL
;
67 case SOLVER_TRANSACTION_ERASE
:
68 return PAKFIRE_STEP_ERASE
;
70 case SOLVER_TRANSACTION_DOWNGRADE
:
71 return PAKFIRE_STEP_DOWNGRADE
;
73 case SOLVER_TRANSACTION_UPGRADE
:
74 return PAKFIRE_STEP_UPGRADE
;
76 case SOLVER_TRANSACTION_OBSOLETES
:
77 return PAKFIRE_STEP_OBSOLETE
;
79 // Anything we don't care about
80 case SOLVER_TRANSACTION_IGNORE
:
81 case SOLVER_TRANSACTION_REINSTALLED
:
82 case SOLVER_TRANSACTION_DOWNGRADED
:
84 return PAKFIRE_STEP_IGNORE
;
88 static void pakfire_transaction_free_archives_and_packages(
89 struct pakfire_transaction
* transaction
) {
90 if (transaction
->archives
) {
91 for (unsigned int i
= 0; i
< transaction
->num
; i
++)
92 if (transaction
->archives
[i
])
93 pakfire_archive_unref(transaction
->archives
[i
]);
94 free(transaction
->archives
);
96 transaction
->archives
= NULL
;
99 if (transaction
->packages
) {
100 for (unsigned int i
= 0; i
< transaction
->num
; i
++)
101 if (transaction
->packages
[i
])
102 pakfire_package_unref(transaction
->packages
[i
]);
103 free(transaction
->packages
);
105 transaction
->packages
= NULL
;
109 static void pakfire_transaction_free(struct pakfire_transaction
* transaction
) {
110 pakfire_transaction_free_archives_and_packages(transaction
);
112 transaction_free(transaction
->transaction
);
114 pakfire_unref(transaction
->pakfire
);
118 static int pakfire_transaction_import_transaction(
119 struct pakfire_transaction
* transaction
, Transaction
* t
) {
120 // Free any previous content
121 pakfire_transaction_free_archives_and_packages(transaction
);
123 // Order the transaction
124 transaction_order(t
, 0);
127 transaction
->num
= t
->steps
.count
;
129 // Allocate space for packages
130 transaction
->packages
= calloc(transaction
->num
, sizeof(*transaction
->packages
));
131 if (!transaction
->packages
)
134 // Allocate space for archives
135 transaction
->archives
= calloc(transaction
->num
, sizeof(*transaction
->archives
));
136 if (!transaction
->archives
)
139 // Create all packages
140 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
141 transaction
->packages
[i
] = pakfire_package_create_from_solvable(
142 transaction
->pakfire
, t
->steps
.elements
[i
]);
148 int pakfire_transaction_create(struct pakfire_transaction
** transaction
,
149 Pakfire pakfire
, Transaction
* trans
) {
150 struct pakfire_transaction
* t
= calloc(1, sizeof(*t
));
154 // Store reference to Pakfire
155 t
->pakfire
= pakfire_ref(pakfire
);
157 // Initialize the reference counter
160 // Clone the transaction to keep a copy of it
161 t
->transaction
= transaction_create_clone(trans
);
165 // Import transaction
166 int r
= pakfire_transaction_import_transaction(t
, t
->transaction
);
174 pakfire_transaction_free(t
);
179 PAKFIRE_EXPORT
struct pakfire_transaction
* pakfire_transaction_ref(
180 struct pakfire_transaction
* transaction
) {
181 transaction
->nrefs
++;
186 PAKFIRE_EXPORT
struct pakfire_transaction
* pakfire_transaction_unref(
187 struct pakfire_transaction
* transaction
) {
188 if (--transaction
->nrefs
> 0)
191 pakfire_transaction_free(transaction
);
195 PAKFIRE_EXPORT
size_t pakfire_transaction_count(struct pakfire_transaction
* transaction
) {
196 return transaction
->num
;
199 static ssize_t
pakfire_transaction_installsizechange(struct pakfire_transaction
* transaction
) {
200 ssize_t sizechange
= transaction_calc_installsizechange(transaction
->transaction
);
202 // Convert from kbytes to bytes
203 return sizechange
* 1024;
206 PAKFIRE_EXPORT ssize_t
pakfire_transaction_downloadsize(struct pakfire_transaction
* transaction
) {
209 for (unsigned int i
= 0; i
< transaction
->num
; i
++)
210 size
+= pakfire_package_get_downloadsize(transaction
->packages
[i
]);
215 static void pakfire_transaction_add_headline(char** str
, size_t width
, const char* headline
) {
216 asprintf(str
, "%s%s\n", *str
, headline
);
219 static void pakfire_transaction_add_newline(char** str
, size_t width
) {
220 asprintf(str
, "%s\n", *str
);
223 static void pakfire_transaction_add_line(char** str
, size_t width
, const char* name
,
224 const char* arch
, const char* version
, const char* repo
, const char* size
) {
225 // XXX need to adapt to size
226 asprintf(str
, "%s %-21s %-8s %-21s %-18s %6s \n", *str
, name
, arch
, version
, repo
, size
);
229 static void pakfire_transaction_add_package(char** str
, size_t width
, PakfirePackage pkg
) {
232 PakfireRepo repo
= pakfire_package_get_repo(pkg
);
235 pakfire_format_size(size
, sizeof(size
) - 1, pakfire_package_get_size(pkg
));
237 pakfire_transaction_add_line(str
, width
,
238 pakfire_package_get_name(pkg
),
239 pakfire_package_get_arch(pkg
),
240 pakfire_package_get_evr(pkg
),
241 pakfire_repo_get_name(repo
),
245 pakfire_repo_unref(repo
);
248 static void pakfire_transaction_add_package_change(char** str
, size_t width
,
249 PakfirePackage old_pkg
, PakfirePackage new_pkg
) {
250 // Print the new package first
251 pakfire_transaction_add_package(str
, width
, new_pkg
);
253 asprintf(str
, "%s --> %s\n", *str
, pakfire_package_get_nevra(old_pkg
));
256 static void pakfire_transaction_add_separator(char** str
, size_t width
) {
258 asprintf(str
, "%s=", *str
);
261 asprintf(str
, "%s\n", *str
);
264 static void pakfire_transaction_add_usage_line(char** str
, size_t width
, const char* headline
, ssize_t size
) {
266 pakfire_format_size(buffer
, sizeof(buffer
) - 1, size
);
268 asprintf(str
, "%s%-21s: %s\n", *str
, headline
, buffer
);
271 PAKFIRE_EXPORT
char* pakfire_transaction_dump(struct pakfire_transaction
* transaction
, size_t width
) {
275 Pool
* pool
= transaction
->transaction
->pool
;
277 SOLVER_TRANSACTION_SHOW_OBSOLETES
|
278 SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE
;
281 pakfire_transaction_add_separator(&string
, width
);
282 pakfire_transaction_add_line(&string
, width
,
289 pakfire_transaction_add_separator(&string
, width
);
292 queue_init(&classes
);
295 transaction_classify(transaction
->transaction
, mode
, &classes
);
301 The classes queue now contains a list of all classes as a tuple of:
303 * The number of packages in this class
304 * The from ID (for arch/vendor change)
305 * The to ID (for arch/vendor change)
307 for (int i
= 0; i
< classes
.count
; i
+= 4) {
308 Id
class = classes
.elements
[i
];
309 unsigned int count
= classes
.elements
[i
+1];
311 const char* from
= pool_id2str(pool
, classes
.elements
[i
+2]);
312 const char* to
= pool_id2str(pool
, classes
.elements
[i
+3]);
315 case SOLVER_TRANSACTION_INSTALL
:
317 pakfire_string_format(headline
, _("Installing %u packages:"), count
);
319 pakfire_string_set(headline
, _("Installing one package:"));
322 case SOLVER_TRANSACTION_REINSTALLED
:
324 pakfire_string_format(headline
, _("Reinstalling %u packages:"), count
);
326 pakfire_string_set(headline
, _("Reinstalling one package:"));
329 case SOLVER_TRANSACTION_ERASE
:
331 pakfire_string_format(headline
, _("Removing %u packages:"), count
);
333 pakfire_string_set(headline
, _("Removing one package:"));
336 case SOLVER_TRANSACTION_UPGRADED
:
338 pakfire_string_format(headline
, _("Updating %u packages:"), count
);
340 pakfire_string_set(headline
, _("Updating one package:"));
343 case SOLVER_TRANSACTION_DOWNGRADED
:
345 pakfire_string_format(headline
, _("Downgrading %u packages:"), count
);
347 pakfire_string_set(headline
, _("Downgrading one package:"));
350 case SOLVER_TRANSACTION_CHANGED
:
352 pakfire_string_format(headline
, _("Changing %u packages:"), count
);
354 pakfire_string_set(headline
, _("Changing one package:"));
357 case SOLVER_TRANSACTION_ARCHCHANGE
:
359 pakfire_string_format(headline
,
360 _("%u architecture changes from '%s' to '%s':"), count
, from
, to
);
362 pakfire_string_format(headline
,
363 _("One architecture change from '%s' to '%s':"), from
, to
);
366 case SOLVER_TRANSACTION_VENDORCHANGE
:
368 pakfire_string_format(headline
,
369 _("%u vendor changes from '%s' to '%s':"), count
, from
, to
);
371 pakfire_string_format(headline
,
372 _("One vendor change from '%s' to '%s':"), from
, to
);
375 case SOLVER_TRANSACTION_IGNORE
:
379 // Show what we are doing
380 pakfire_transaction_add_headline(&string
, width
, headline
);
382 // Fetch packages in this class
383 transaction_classify_pkgs(transaction
->transaction
, mode
, class,
384 classes
.elements
[i
+2], classes
.elements
[i
+3], &pkgs
);
387 for (int j
= 0; j
< pkgs
.count
; j
++) {
388 PakfirePackage old_pkg
= pakfire_package_create_from_solvable(
389 transaction
->pakfire
, pkgs
.elements
[j
]);
390 PakfirePackage new_pkg
= NULL
;
393 case SOLVER_TRANSACTION_UPGRADED
:
394 case SOLVER_TRANSACTION_DOWNGRADED
:
395 new_pkg
= pakfire_package_create_from_solvable(transaction
->pakfire
,
396 transaction_obs_pkg(transaction
->transaction
, pkgs
.elements
[j
]));
398 pakfire_transaction_add_package_change(&string
, width
, old_pkg
, new_pkg
);
402 pakfire_transaction_add_package(&string
, width
, old_pkg
);
406 pakfire_package_unref(old_pkg
);
408 pakfire_package_unref(new_pkg
);
412 pakfire_transaction_add_newline(&string
, width
);
415 queue_free(&classes
);
419 pakfire_transaction_add_headline(&string
, width
, _("Transaction Summary"));
420 pakfire_transaction_add_separator(&string
, width
);
422 // How much do we need to download?
423 size_t downloadsize
= pakfire_transaction_downloadsize(transaction
);
425 if (downloadsize
> 0)
426 pakfire_transaction_add_usage_line(&string
, width
,
427 _("Total Download Size"), downloadsize
);
429 // How much more space do we need?
430 ssize_t sizechange
= pakfire_transaction_installsizechange(transaction
);
431 pakfire_transaction_add_usage_line(&string
, width
,
432 (sizechange
>= 0) ? _("Installed Size") : _("Freed Size"), sizechange
);
434 // Remove trailing newline
435 pakfire_remove_trailing_newline(string
);
437 DEBUG(transaction
->pakfire
, "Transaction: %s\n", string
);
442 static int pakfire_transaction_verify(struct pakfire_transaction
* transaction
,
443 PakfirePackage pkg
, PakfireArchive archive
) {
444 // Nothing to do if this step does not have an archive
448 // Verify the archive
449 pakfire_archive_verify_status_t status
= pakfire_archive_verify(archive
);
453 const char* error
= pakfire_archive_verify_strerror(status
);
454 ERROR(transaction
->pakfire
, "Archive verification failed: %s\n", error
);
460 static int pakfire_transaction_run_script(struct pakfire_transaction
* transaction
,
461 struct pakfire_db
* db
, const char* type
, PakfirePackage pkg
, PakfireArchive archive
) {
462 struct pakfire_scriptlet
* scriptlet
= NULL
;
464 // Fetch scriptlet from archive if possible
466 scriptlet
= pakfire_archive_get_scriptlet(archive
, type
);
468 scriptlet
= pakfire_db_get_scriptlet(db
, pkg
, type
);
470 // Nothing to do if there are no scriptlets
474 // Execute the scriptlet
475 pakfire_scriptlet_execute(scriptlet
);
477 pakfire_scriptlet_unref(scriptlet
);
482 static int pakfire_transaction_extract(struct pakfire_transaction
* transaction
,
483 PakfirePackage pkg
, PakfireArchive archive
) {
484 // Extract payload to the root of the Pakfire instance
485 int r
= pakfire_archive_extract(archive
, NULL
);
487 ERROR(transaction
->pakfire
, "Could not extract package %s: %s\n",
488 pakfire_package_get_nevra(pkg
), strerror(errno
));
492 // Is it necessary to call ldconfig?
493 PakfireFilelist filelist
= pakfire_archive_get_filelist(archive
);
495 int need_ldconfig
= pakfire_filelist_contains(filelist
, "*/lib*.so.?");
497 // Update the runtime linker cache
499 pakfire_execute_ldconfig(transaction
->pakfire
);
501 pakfire_filelist_unref(filelist
);
507 static int pakfire_transaction_erase(struct pakfire_transaction
* transaction
,
508 PakfirePackage pkg
, PakfireArchive archive
) {
509 // Update the runtime linker cache after all files have been removed
510 pakfire_execute_ldconfig(transaction
->pakfire
);
515 static const char* pakfire_action_type_string(pakfire_action_type_t type
) {
517 case PAKFIRE_ACTION_NOOP
:
520 case PAKFIRE_ACTION_VERIFY
:
523 case PAKFIRE_ACTION_EXECUTE
:
526 case PAKFIRE_ACTION_PRETRANS
:
529 case PAKFIRE_ACTION_POSTTRANS
:
536 static int pakfire_transaction_run_step(struct pakfire_transaction
* transaction
,
537 struct pakfire_db
* db
, const pakfire_action_type_t action
, PakfirePackage pkg
, PakfireArchive archive
) {
543 DEBUG(transaction
->pakfire
, "Running %s for %s\n",
544 pakfire_action_type_string(action
), pakfire_package_get_nevra(pkg
));
546 pakfire_step_type_t type
= pakfire_transaction_get_step_type(transaction
, pkg
);
551 case PAKFIRE_ACTION_VERIFY
:
552 r
= pakfire_transaction_verify(transaction
, pkg
, archive
);
555 // Run the pre-transaction scripts
556 case PAKFIRE_ACTION_PRETRANS
:
558 case PAKFIRE_STEP_INSTALL
:
559 case PAKFIRE_STEP_REINSTALL
:
560 r
= pakfire_transaction_run_script(transaction
, db
,
561 "pretransin", pkg
, archive
);
564 case PAKFIRE_STEP_UPGRADE
:
565 case PAKFIRE_STEP_DOWNGRADE
:
566 r
= pakfire_transaction_run_script(transaction
, db
,
567 "pretransup", pkg
, archive
);
570 case PAKFIRE_STEP_ERASE
:
571 case PAKFIRE_STEP_OBSOLETE
:
572 r
= pakfire_transaction_run_script(transaction
, db
,
573 "pretransun", pkg
, archive
);
576 case PAKFIRE_STEP_IGNORE
:
581 // Run the post-transaction scripts
582 case PAKFIRE_ACTION_POSTTRANS
:
584 case PAKFIRE_STEP_INSTALL
:
585 case PAKFIRE_STEP_REINSTALL
:
586 r
= pakfire_transaction_run_script(transaction
, db
,
587 "posttransin", pkg
, archive
);
590 case PAKFIRE_STEP_UPGRADE
:
591 case PAKFIRE_STEP_DOWNGRADE
:
592 r
= pakfire_transaction_run_script(transaction
, db
,
593 "posttransup", pkg
, archive
);
596 case PAKFIRE_STEP_ERASE
:
597 case PAKFIRE_STEP_OBSOLETE
:
598 r
= pakfire_transaction_run_script(transaction
, db
,
599 "posttransun", pkg
, archive
);
602 case PAKFIRE_STEP_IGNORE
:
607 // Execute the action of this script
608 case PAKFIRE_ACTION_EXECUTE
:
610 case PAKFIRE_STEP_INSTALL
:
611 case PAKFIRE_STEP_REINSTALL
:
612 r
= pakfire_transaction_run_script(transaction
, db
,
613 "prein", pkg
, archive
);
617 r
= pakfire_transaction_extract(transaction
, pkg
, archive
);
621 // Remove package metadata first when reinstalling
622 if (type
== PAKFIRE_STEP_REINSTALL
) {
623 r
= pakfire_db_remove_package(db
, pkg
);
628 r
= pakfire_db_add_package(db
, pkg
, archive
);
632 r
= pakfire_transaction_run_script(transaction
, db
,
633 "postin", pkg
, archive
);
636 case PAKFIRE_STEP_UPGRADE
:
637 case PAKFIRE_STEP_DOWNGRADE
:
638 r
= pakfire_transaction_run_script(transaction
, db
,
639 "preup", pkg
, archive
);
643 r
= pakfire_transaction_extract(transaction
, pkg
, archive
);
647 r
= pakfire_db_add_package(db
, pkg
, archive
);
651 r
= pakfire_transaction_run_script(transaction
, db
,
652 "postup", pkg
, archive
);
655 case PAKFIRE_STEP_ERASE
:
656 case PAKFIRE_STEP_OBSOLETE
:
657 r
= pakfire_transaction_run_script(transaction
, db
,
658 "preun", pkg
, archive
);
662 r
= pakfire_transaction_erase(transaction
, pkg
, archive
);
666 r
= pakfire_db_remove_package(db
, pkg
);
670 r
= pakfire_transaction_run_script(transaction
, db
,
671 "postun", pkg
, archive
);
674 case PAKFIRE_STEP_IGNORE
:
680 case PAKFIRE_ACTION_NOOP
:
685 ERROR(transaction
->pakfire
, "Step has failed: %s\n", strerror(r
));
690 static int pakfire_transaction_run_steps(struct pakfire_transaction
* transaction
,
691 struct pakfire_db
* db
, const pakfire_action_type_t action
) {
694 // Walk through all steps
695 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
696 r
= pakfire_transaction_run_step(transaction
, db
, action
,
697 transaction
->packages
[i
], transaction
->archives
[i
]);
699 // End loop if action was unsuccessful
701 DEBUG(transaction
->pakfire
, "Step %d failed: %s\n", i
, strerror(errno
));
709 static int pakfire_transaction_open_archives(struct pakfire_transaction
* transaction
) {
710 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
711 PakfirePackage pkg
= transaction
->packages
[i
];
714 pakfire_step_type_t type
= pakfire_transaction_get_step_type(transaction
, pkg
);
716 // Do we need the archive?
718 case PAKFIRE_STEP_INSTALL
:
719 case PAKFIRE_STEP_REINSTALL
:
720 case PAKFIRE_STEP_UPGRADE
:
721 case PAKFIRE_STEP_DOWNGRADE
:
722 case PAKFIRE_STEP_OBSOLETE
:
725 case PAKFIRE_STEP_ERASE
:
726 case PAKFIRE_STEP_IGNORE
:
730 transaction
->archives
[i
] = pakfire_package_get_archive(pkg
);
731 if (!transaction
->archives
[i
]) {
732 ERROR(transaction
->pakfire
, "Could not open archive for %s: %s\n",
733 pakfire_package_get_nevra(pkg
), strerror(errno
));
741 static int pakfire_transaction_perform(struct pakfire_transaction
* transaction
) {
742 PakfireRepo repo
= NULL
;
743 struct pakfire_db
* db
;
746 DEBUG(transaction
->pakfire
, "Running Transaction %p\n", transaction
);
749 r
= pakfire_transaction_open_archives(transaction
);
754 r
= pakfire_db_open(&db
, transaction
->pakfire
, PAKFIRE_DB_READWRITE
);
756 ERROR(transaction
->pakfire
, "Could not open the database\n");
761 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_VERIFY
);
765 // Execute all pre transaction actions
766 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_PRETRANS
);
770 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_EXECUTE
);
774 // Execute all post transaction actions
775 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_POSTTRANS
);
779 DEBUG(transaction
->pakfire
, "The transaction has finished successfully\n");
781 // Reload database for next transaction
783 repo
= pakfire_get_installed_repo(transaction
->pakfire
);
787 // Reload the database
788 r
= pakfire_db_load(db
, repo
);
792 pakfire_repo_unref(repo
);
793 pakfire_db_unref(db
);
798 static int pakfire_transaction_download_package(struct pakfire_transaction
* transaction
,
799 struct pakfire_downloader
* downloader
, PakfirePackage pkg
) {
801 PakfireRepo repo
= NULL
;
802 struct pakfire_mirrorlist
* mirrorlist
= NULL
;
804 // Fetch the repository to download from
805 repo
= pakfire_package_get_repo(pkg
);
810 const char* baseurl
= pakfire_repo_get_baseurl(repo
);
813 mirrorlist
= pakfire_repo_get_mirrorlist(repo
);
815 // Where to store the package?
816 const char* path
= pakfire_package_get_path(pkg
);
820 // What file to download?
821 const char* filename
= pakfire_package_get_filename(pkg
);
825 const char* nevra
= pakfire_package_get_nevra(pkg
);
829 // Add transfer to downloader
830 r
= pakfire_downloader_add_transfer(downloader
, baseurl
, mirrorlist
,
831 nevra
, filename
, path
, 0);
835 pakfire_mirrorlist_unref(mirrorlist
);
837 pakfire_repo_unref(repo
);
842 static int pakfire_transaction_package_needs_download(
843 struct pakfire_transaction
* transaction
, PakfirePackage pkg
) {
844 pakfire_step_type_t type
= pakfire_transaction_get_step_type(transaction
, pkg
);
846 case PAKFIRE_STEP_INSTALL
:
847 case PAKFIRE_STEP_REINSTALL
:
848 case PAKFIRE_STEP_DOWNGRADE
:
849 case PAKFIRE_STEP_UPGRADE
:
852 // No need to download for these steps
857 // No download required if this package is already installed
858 if (pakfire_package_is_installed(pkg
))
861 const char* path
= pakfire_package_get_path(pkg
);
863 // Does the file exist?
864 int r
= access(path
, R_OK
);
868 // This package needs to be downloaded
872 PAKFIRE_EXPORT
int pakfire_transaction_download(struct pakfire_transaction
* transaction
) {
873 struct pakfire_downloader
* downloader
;
876 // Initialize the downloader
877 r
= pakfire_downloader_create(&downloader
, transaction
->pakfire
);
879 ERROR(transaction
->pakfire
, "Could not initialize downloader: %s\n",
884 // Add all packages that need to be downloaded
885 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
886 PakfirePackage pkg
= transaction
->packages
[i
];
888 if (!pakfire_transaction_package_needs_download(transaction
, pkg
))
892 r
= pakfire_transaction_download_package(transaction
, downloader
, pkg
);
897 // Run the downloader
898 r
= pakfire_downloader_run(downloader
);
901 pakfire_downloader_unref(downloader
);
906 PAKFIRE_EXPORT
int pakfire_transaction_run(struct pakfire_transaction
* transaction
) {
909 // Skip running an empty transaction
910 if (!transaction
->num
) {
911 DEBUG(transaction
->pakfire
, "Empty transaction. Skipping...\n");
915 // Show what would be done
916 char* dump
= pakfire_transaction_dump(transaction
, 80);
918 // Check if we should continue
919 r
= pakfire_ui_confirm(transaction
->pakfire
, dump
, _("Is this okay? [y/N]"));
921 ERROR(transaction
->pakfire
, "Transaction aborted upon user request\n");
925 // Write transaction dump to log
926 INFO(transaction
->pakfire
, "%s\n", dump
);
928 // Download what we need
929 r
= pakfire_transaction_download(transaction
);
934 r
= pakfire_transaction_perform(transaction
);