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/package.h>
26 #include <pakfire/packagelist.h>
27 #include <pakfire/repo.h>
28 #include <pakfire/step.h>
29 #include <pakfire/transaction.h>
30 #include <pakfire/types.h>
31 #include <pakfire/util.h>
33 PakfireTransaction
pakfire_transaction_create(PakfirePool pool
, Transaction
* trans
) {
34 PakfireTransaction transaction
= pakfire_calloc(1, sizeof(*transaction
));
35 transaction
->pool
= pool
;
37 // Clone the transaction, so we get independent from what ever called this.
39 transaction
->transaction
= transaction_create_clone(trans
);
40 transaction_order(transaction
->transaction
, 0);
42 transaction
->transaction
= transaction_create(trans
->pool
);
48 void pakfire_transaction_free(PakfireTransaction transaction
) {
49 transaction_free(transaction
->transaction
);
50 pakfire_free(transaction
);
53 size_t pakfire_transaction_count(PakfireTransaction transaction
) {
54 return transaction
->transaction
->steps
.count
;
57 ssize_t
pakfire_transaction_installsizechange(PakfireTransaction transaction
) {
58 ssize_t sizechange
= transaction_calc_installsizechange(transaction
->transaction
);
60 // Convert from kbytes to bytes
61 return sizechange
* 1024;
64 ssize_t
pakfire_transaction_downloadsize(PakfireTransaction transaction
) {
65 PakfirePool pool
= pakfire_transaction_pool(transaction
);
68 for (int i
= 0; i
< transaction
->transaction
->steps
.count
; i
++) {
69 Id p
= transaction
->transaction
->steps
.elements
[i
];
70 Id t
= transaction_type(transaction
->transaction
, p
,
71 SOLVER_TRANSACTION_SHOW_OBSOLETES
|
72 SOLVER_TRANSACTION_CHANGE_IS_REINSTALL
|
73 SOLVER_TRANSACTION_SHOW_ALL
|
74 SOLVER_TRANSACTION_SHOW_ACTIVE
);
76 // Erasing a package does not require us to download it
77 if (t
== SOLVER_TRANSACTION_ERASE
)
80 // Get the package for this step
81 PakfirePackage pkg
= pakfire_package_create(pool
, p
);
83 if (!pakfire_package_is_cached(pkg
))
84 size
+= pakfire_package_get_downloadsize(pkg
);
86 pakfire_package_free(pkg
);
92 PakfireStep
pakfire_transaction_get_step(PakfireTransaction transaction
, int index
) {
93 Transaction
* trans
= transaction
->transaction
;
95 if (index
>= trans
->steps
.count
)
98 return pakfire_step_create(transaction
, trans
->steps
.elements
[index
]);
101 PakfirePackageList
pakfire_transaction_get_packages(PakfireTransaction transaction
, int type
) {
102 PakfirePool pool
= pakfire_transaction_pool(transaction
);
104 PakfirePackageList packagelist
= pakfire_packagelist_create();
106 for (int i
= 0; i
< transaction
->transaction
->steps
.count
; i
++) {
107 Id p
= transaction
->transaction
->steps
.elements
[i
];
108 Id t
= transaction_type(transaction
->transaction
, p
,
109 SOLVER_TRANSACTION_SHOW_OBSOLETES
|
110 SOLVER_TRANSACTION_CHANGE_IS_REINSTALL
|
111 SOLVER_TRANSACTION_SHOW_ALL
|
112 SOLVER_TRANSACTION_SHOW_ACTIVE
);
115 PakfirePackage package
= pakfire_package_create(pool
, p
);
116 pakfire_packagelist_push(packagelist
, package
);
120 // Sort list in place
121 pakfire_packagelist_sort(packagelist
);
126 static void pakfire_transaction_add_headline(char** str
, size_t width
, const char* headline
) {
129 asprintf(str
, "%s%s\n", *str
, headline
);
132 static void pakfire_transaction_add_newline(char** str
, size_t width
) {
133 asprintf(str
, "%s\n", *str
);
136 static void pakfire_transaction_add_line(char** str
, size_t width
, const char* name
,
137 const char* arch
, const char* version
, const char* repo
, const char* size
) {
138 // XXX need to adapt to size
139 asprintf(str
, "%s %-21s %-8s %-21s %-18s %6s \n", *str
, name
, arch
, version
, repo
, size
);
142 static void pakfire_transaction_add_package(char** str
, size_t width
, PakfirePackage pkg
) {
143 PakfireRepo repo
= pakfire_package_get_repo(pkg
);
145 unsigned long long size
= pakfire_package_get_size(pkg
);
146 char* size_str
= pakfire_format_size(size
);
148 pakfire_transaction_add_line(str
, width
,
149 pakfire_package_get_name(pkg
),
150 pakfire_package_get_arch(pkg
),
151 pakfire_package_get_evr(pkg
),
152 pakfire_repo_get_name(repo
),
156 pakfire_repo_free(repo
);
157 pakfire_free(size_str
);
160 static void pakfire_transaction_add_separator(char** str
, size_t width
) {
162 asprintf(str
, "%s=", *str
);
165 asprintf(str
, "%s\n", *str
);
168 static size_t pakfire_transaction_add_section(char** str
, size_t width
, PakfireTransaction transaction
,
169 const char* headline
, int type
) {
170 PakfirePackageList list
= pakfire_transaction_get_packages(transaction
, type
);
172 // Nothing to do if there are no packages in this stage
173 size_t c
= pakfire_packagelist_count(list
);
178 pakfire_transaction_add_headline(str
, width
, headline
);
181 for (unsigned int i
= 0; i
< c
; i
++) {
182 PakfirePackage pkg
= pakfire_packagelist_get(list
, i
);
183 pakfire_transaction_add_package(str
, width
, pkg
);
187 pakfire_transaction_add_newline(str
, width
);
190 pakfire_packagelist_free(list
);
195 static void pakfire_transaction_add_summary_line(char** str
, size_t width
, const char* headline
, size_t pkgs
) {
197 asprintf(str
, "%s%-20s %-4zu %s\n", *str
, headline
, pkgs
, _("package(s)"));
200 static void pakfire_transaction_add_usage_line(char** str
, size_t width
, const char* headline
, ssize_t size
) {
201 char* s
= pakfire_format_size(size
);
203 asprintf(str
, "%s%-21s: %s\n", *str
, headline
, s
);
208 char* pakfire_transaction_dump(PakfireTransaction transaction
, size_t width
) {
212 pakfire_transaction_add_separator(&string
, width
);
213 pakfire_transaction_add_line(&string
, width
,
220 pakfire_transaction_add_separator(&string
, width
);
222 // Show what we are doing
223 size_t installing
= pakfire_transaction_add_section(&string
, width
, transaction
,
224 _("Installing:"), SOLVER_TRANSACTION_INSTALL
);
225 size_t reinstalling
= pakfire_transaction_add_section(&string
, width
, transaction
,
226 _("Reinstalling:"), SOLVER_TRANSACTION_REINSTALL
);
227 size_t updating
= pakfire_transaction_add_section(&string
, width
, transaction
,
228 _("Updating:"), SOLVER_TRANSACTION_UPGRADE
);
229 size_t downgrading
= pakfire_transaction_add_section(&string
, width
, transaction
,
230 _("Downgrading:"), SOLVER_TRANSACTION_DOWNGRADE
);
231 size_t removing
= pakfire_transaction_add_section(&string
, width
, transaction
,
232 _("Removing:"), SOLVER_TRANSACTION_ERASE
);
233 size_t obsoleting
= pakfire_transaction_add_section(&string
, width
, transaction
,
234 _("Obsoleting:"), SOLVER_TRANSACTION_OBSOLETES
);
237 pakfire_transaction_add_headline(&string
, width
, _("Transaction Summary"));
238 pakfire_transaction_add_separator(&string
, width
);
240 pakfire_transaction_add_summary_line(&string
, width
, _("Installing:"), installing
);
241 pakfire_transaction_add_summary_line(&string
, width
, _("Reinstalling:"), reinstalling
);
242 pakfire_transaction_add_summary_line(&string
, width
, _("Updating:"), updating
);
243 pakfire_transaction_add_summary_line(&string
, width
, _("Downgrading:"), downgrading
);
244 pakfire_transaction_add_summary_line(&string
, width
, _("Removing:"), removing
);
245 pakfire_transaction_add_summary_line(&string
, width
, _("Obsoleting:"), obsoleting
);
247 // How much do we need to download?
248 size_t downloadsize
= pakfire_transaction_downloadsize(transaction
);
249 if (downloadsize
> 0)
250 pakfire_transaction_add_usage_line(&string
, width
,
251 _("Total Download Size"), downloadsize
);
253 // How much more space do we need?
254 ssize_t sizechange
= pakfire_transaction_installsizechange(transaction
);
256 pakfire_transaction_add_usage_line(&string
, width
,
257 (sizechange
>= 0) ? _("Installed Size") : _("Freed Size"), sizechange
);
259 // Remove trailing newline
260 size_t l
= strlen(string
) - 1;
262 if (l
> 0 && string
[l
] == '\n')
268 static int pakfire_transaction_run_steps(PakfireTransaction transaction
, const pakfire_action_type action
) {
269 size_t steps
= pakfire_transaction_count(transaction
);
271 // Walk through all steps
273 for (unsigned int i
= 0; i
< steps
; i
++) {
274 PakfireStep step
= pakfire_transaction_get_step(transaction
, i
);
277 r
= pakfire_step_run(step
, action
);
280 pakfire_step_free(step
);
282 // End loop if action was unsuccessful
290 int pakfire_transaction_run(PakfireTransaction transaction
) {
294 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_VERIFY
);
298 // Execute all pre transaction actions
299 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_PRETRANS
);
303 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_EXECUTE
);
307 // Execute all post transaction actions
308 r
= pakfire_transaction_run_steps(transaction
, PAKFIRE_ACTION_POSTTRANS
);