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 #############################################################################*/
22 #include <solv/transaction.h>
24 #include <pakfire/i18n.h>
25 #include <pakfire/logging.h>
26 #include <pakfire/package.h>
27 #include <pakfire/packagelist.h>
28 #include <pakfire/pool.h>
29 #include <pakfire/private.h>
30 #include <pakfire/repo.h>
31 #include <pakfire/step.h>
32 #include <pakfire/transaction.h>
33 #include <pakfire/types.h>
34 #include <pakfire/util.h>
36 struct _PakfireTransaction
{
38 Transaction
* transaction
;
43 PAKFIRE_EXPORT PakfireTransaction
pakfire_transaction_create(PakfirePool pool
, Transaction
* trans
) {
44 PakfireTransaction transaction
= pakfire_calloc(1, sizeof(*transaction
));
46 DEBUG("Allocated Transaction at %p\n", transaction
);
47 transaction
->nrefs
= 1;
49 transaction
->pool
= pakfire_pool_ref(pool
);
51 // Clone the transaction, so we get independent from what ever called this.
53 transaction
->transaction
= transaction_create_clone(trans
);
54 transaction_order(transaction
->transaction
, 0);
56 transaction
->transaction
= transaction_create(trans
->pool
);
63 PAKFIRE_EXPORT PakfireTransaction
pakfire_transaction_ref(PakfireTransaction transaction
) {
71 void pakfire_transaction_free(PakfireTransaction transaction
) {
72 pakfire_pool_unref(transaction
->pool
);
74 transaction_free(transaction
->transaction
);
75 pakfire_free(transaction
);
77 DEBUG("Released Transaction at %p\n", transaction
);
80 PAKFIRE_EXPORT PakfireTransaction
pakfire_transaction_unref(PakfireTransaction transaction
) {
84 if (--transaction
->nrefs
> 0)
87 pakfire_transaction_free(transaction
);
91 PAKFIRE_EXPORT PakfirePool
pakfire_transaction_get_pool(PakfireTransaction transaction
) {
92 return pakfire_pool_ref(transaction
->pool
);
95 Transaction
* pakfire_transaction_get_transaction(PakfireTransaction transaction
) {
96 return transaction
->transaction
;
99 PAKFIRE_EXPORT
size_t pakfire_transaction_count(PakfireTransaction transaction
) {
100 return transaction
->transaction
->steps
.count
;
103 PAKFIRE_EXPORT ssize_t
pakfire_transaction_installsizechange(PakfireTransaction transaction
) {
104 ssize_t sizechange
= transaction_calc_installsizechange(transaction
->transaction
);
106 // Convert from kbytes to bytes
107 return sizechange
* 1024;
110 PAKFIRE_EXPORT ssize_t
pakfire_transaction_downloadsize(PakfireTransaction transaction
) {
113 size_t steps
= pakfire_transaction_count(transaction
);
114 for (unsigned int i
= 0; i
< steps
; i
++) {
115 PakfireStep step
= pakfire_transaction_get_step(transaction
, i
);
116 size
+= pakfire_step_get_downloadsize(step
);
118 pakfire_step_unref(step
);
124 PAKFIRE_EXPORT PakfireStep
pakfire_transaction_get_step(PakfireTransaction transaction
, int index
) {
125 Transaction
* trans
= transaction
->transaction
;
127 if (index
>= trans
->steps
.count
)
130 return pakfire_step_create(transaction
, trans
->steps
.elements
[index
]);
133 PAKFIRE_EXPORT PakfirePackageList
pakfire_transaction_get_packages(PakfireTransaction transaction
, pakfire_step_type_t type
) {
134 PakfirePackageList packagelist
= pakfire_packagelist_create();
136 size_t steps
= pakfire_transaction_count(transaction
);
137 for (unsigned int i
= 0; i
< steps
; i
++) {
138 PakfireStep step
= pakfire_transaction_get_step(transaction
, i
);
140 if (pakfire_step_get_type(step
) == type
) {
141 PakfirePackage package
= pakfire_step_get_package(step
);
142 pakfire_packagelist_push(packagelist
, package
);
144 pakfire_package_unref(package
);
147 pakfire_step_unref(step
);
150 // Sort list in place
151 pakfire_packagelist_sort(packagelist
);
156 static void pakfire_transaction_add_headline(char** str
, size_t width
, const char* headline
) {
159 asprintf(str
, "%s%s\n", *str
, headline
);
162 static void pakfire_transaction_add_newline(char** str
, size_t width
) {
163 asprintf(str
, "%s\n", *str
);
166 static void pakfire_transaction_add_line(char** str
, size_t width
, const char* name
,
167 const char* arch
, const char* version
, const char* repo
, const char* size
) {
168 // XXX need to adapt to size
169 asprintf(str
, "%s %-21s %-8s %-21s %-18s %6s \n", *str
, name
, arch
, version
, repo
, size
);
172 static void pakfire_transaction_add_package(char** str
, size_t width
, PakfirePackage pkg
) {
173 PakfireRepo repo
= pakfire_package_get_repo(pkg
);
175 unsigned long long size
= pakfire_package_get_size(pkg
);
176 char* size_str
= pakfire_format_size(size
);
178 pakfire_transaction_add_line(str
, width
,
179 pakfire_package_get_name(pkg
),
180 pakfire_package_get_arch(pkg
),
181 pakfire_package_get_evr(pkg
),
182 pakfire_repo_get_name(repo
),
186 pakfire_repo_free(repo
);
187 pakfire_free(size_str
);
190 static void pakfire_transaction_add_separator(char** str
, size_t width
) {
192 asprintf(str
, "%s=", *str
);
195 asprintf(str
, "%s\n", *str
);
198 static size_t pakfire_transaction_add_section(char** str
, size_t width
, PakfireTransaction transaction
,
199 const char* headline
, pakfire_step_type_t type
) {
200 PakfirePackageList list
= pakfire_transaction_get_packages(transaction
, type
);
202 // Nothing to do if there are no packages in this stage
203 size_t c
= pakfire_packagelist_count(list
);
208 pakfire_transaction_add_headline(str
, width
, headline
);
211 for (unsigned int i
= 0; i
< c
; i
++) {
212 PakfirePackage pkg
= pakfire_packagelist_get(list
, i
);
213 pakfire_transaction_add_package(str
, width
, pkg
);
217 pakfire_transaction_add_newline(str
, width
);
220 pakfire_packagelist_free(list
);
225 static void pakfire_transaction_add_summary_line(char** str
, size_t width
, const char* headline
, size_t pkgs
) {
227 asprintf(str
, "%s%-20s %-4zu %s\n", *str
, headline
, pkgs
, _("package(s)"));
230 static void pakfire_transaction_add_usage_line(char** str
, size_t width
, const char* headline
, ssize_t size
) {
231 char* s
= pakfire_format_size(size
);
233 asprintf(str
, "%s%-21s: %s\n", *str
, headline
, s
);
238 PAKFIRE_EXPORT
char* pakfire_transaction_dump(PakfireTransaction transaction
, size_t width
) {
242 pakfire_transaction_add_separator(&string
, width
);
243 pakfire_transaction_add_line(&string
, width
,
250 pakfire_transaction_add_separator(&string
, width
);
252 // Show what we are doing
253 size_t installing
= pakfire_transaction_add_section(&string
, width
, transaction
,
254 _("Installing:"), PAKFIRE_STEP_INSTALL
);
255 size_t reinstalling
= pakfire_transaction_add_section(&string
, width
, transaction
,
256 _("Reinstalling:"), PAKFIRE_STEP_REINSTALL
);
257 size_t updating
= pakfire_transaction_add_section(&string
, width
, transaction
,
258 _("Updating:"), PAKFIRE_STEP_UPGRADE
);
259 size_t downgrading
= pakfire_transaction_add_section(&string
, width
, transaction
,
260 _("Downgrading:"), PAKFIRE_STEP_DOWNGRADE
);
261 size_t removing
= pakfire_transaction_add_section(&string
, width
, transaction
,
262 _("Removing:"), PAKFIRE_STEP_ERASE
);
263 size_t obsoleting
= pakfire_transaction_add_section(&string
, width
, transaction
,
264 _("Obsoleting:"), PAKFIRE_STEP_OBSOLETE
);
267 pakfire_transaction_add_headline(&string
, width
, _("Transaction Summary"));
268 pakfire_transaction_add_separator(&string
, width
);
270 pakfire_transaction_add_summary_line(&string
, width
, _("Installing:"), installing
);
271 pakfire_transaction_add_summary_line(&string
, width
, _("Reinstalling:"), reinstalling
);
272 pakfire_transaction_add_summary_line(&string
, width
, _("Updating:"), updating
);
273 pakfire_transaction_add_summary_line(&string
, width
, _("Downgrading:"), downgrading
);
274 pakfire_transaction_add_summary_line(&string
, width
, _("Removing:"), removing
);
275 pakfire_transaction_add_summary_line(&string
, width
, _("Obsoleting:"), obsoleting
);
277 // How much do we need to download?
278 size_t downloadsize
= pakfire_transaction_downloadsize(transaction
);
279 if (downloadsize
> 0)
280 pakfire_transaction_add_usage_line(&string
, width
,
281 _("Total Download Size"), downloadsize
);
283 // How much more space do we need?
284 ssize_t sizechange
= pakfire_transaction_installsizechange(transaction
);
286 pakfire_transaction_add_usage_line(&string
, width
,
287 (sizechange
>= 0) ? _("Installed Size") : _("Freed Size"), sizechange
);
289 // Remove trailing newline
290 size_t l
= strlen(string
) - 1;
292 if (l
> 0 && string
[l
] == '\n')
295 DEBUG("Transaction: %s\n", string
);
300 static int pakfire_transaction_run_steps(PakfireTransaction transaction
, const pakfire_action_type action
) {
301 size_t steps
= pakfire_transaction_count(transaction
);
303 // Walk through all steps
305 for (unsigned int i
= 0; i
< steps
; i
++) {
306 PakfireStep step
= pakfire_transaction_get_step(transaction
, i
);
309 r
= pakfire_step_run(step
, action
);
312 pakfire_step_unref(step
);
314 // End loop if action was unsuccessful
322 PAKFIRE_EXPORT
int pakfire_transaction_run(PakfireTransaction transaction
) {
326 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_VERIFY
);
330 // Execute all pre transaction actions
331 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_PRETRANS
);
335 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_EXECUTE
);
339 // Execute all post transaction actions
340 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_POSTTRANS
);