]> git.ipfire.org Git - pakfire.git/blob - src/libpakfire/problem.c
d76f0bcc6575c39b0ab3b883ec75bd4aaac16915
[pakfire.git] / src / libpakfire / problem.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2017 Pakfire development team #
5 # #
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. #
10 # #
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. #
15 # #
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/>. #
18 # #
19 #############################################################################*/
20
21 #include <errno.h>
22 #include <stdlib.h>
23
24 // Enable legacy logging
25 #define PAKFIRE_LEGACY_LOGGING
26
27 #include <pakfire/constants.h>
28 #include <pakfire/dependencies.h>
29 #include <pakfire/i18n.h>
30 #include <pakfire/logging.h>
31 #include <pakfire/pakfire.h>
32 #include <pakfire/private.h>
33 #include <pakfire/problem.h>
34 #include <pakfire/solution.h>
35 #include <pakfire/transaction.h>
36 #include <pakfire/util.h>
37
38 struct pakfire_problem {
39 struct pakfire* pakfire;
40 int nrefs;
41
42 struct pakfire_transaction* transaction;
43 Id id;
44 char* string;
45
46 Solver* solver;
47 };
48
49 static char* pakfire_problem_make_string(struct pakfire_problem* problem) {
50 Solver* solver = pakfire_transaction_get_solver(problem->transaction);
51 Pool* pool = solver->pool;
52
53 // Get the problem rule
54 Id rule = solver_findproblemrule(solver, problem->id);
55
56 // Extract some information about that rule
57 Id dep;
58 Id source;
59 Id target;
60
61 SolverRuleinfo type = solver_ruleinfo(solver, rule, &source, &target, &dep);
62
63 char* s = NULL;
64 int r = 1;
65
66 switch (type) {
67 case SOLVER_RULE_DISTUPGRADE:
68 r = asprintf(&s, _("%s does not belong to a distupgrade repository"),
69 pool_solvid2str(pool, source));
70 break;
71
72 case SOLVER_RULE_INFARCH:
73 r = asprintf(&s, _("%s has inferior architecture"),
74 pool_solvid2str(pool, source));
75 break;
76
77 case SOLVER_RULE_UPDATE:
78 r = asprintf(&s, _("problem with installed package %s"),
79 pool_solvid2str(pool, source));
80 break;
81
82 case SOLVER_RULE_JOB:
83 r = asprintf(&s, _("conflicting requests"));
84 break;
85
86 case SOLVER_RULE_JOB_UNSUPPORTED:
87 r = asprintf(&s, _("unsupported request"));
88 break;
89
90 case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
91 r = asprintf(&s, _("nothing provides requested %s"),
92 pakfire_dep2str(problem->pakfire, dep));
93 break;
94
95 case SOLVER_RULE_JOB_UNKNOWN_PACKAGE:
96 r = asprintf(&s, _("package %s does not exist"),
97 pakfire_dep2str(problem->pakfire, dep));
98 break;
99
100 case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
101 r = asprintf(&s, _("%s is provided by the system"),
102 pakfire_dep2str(problem->pakfire, dep));
103 break;
104
105 case SOLVER_RULE_RPM:
106 r = asprintf(&s, _("some dependency problem"));
107 break;
108
109 case SOLVER_RULE_BEST:
110 if (source > 0)
111 r = asprintf(&s, _("cannot install the best update candidate for package %s"),
112 pool_solvid2str(pool, source));
113 else
114 r = asprintf(&s, _("cannot install the best candidate for the job"));
115 break;
116
117 case SOLVER_RULE_RPM_NOT_INSTALLABLE:
118 r = asprintf(&s, _("package %s is not installable"),
119 pool_solvid2str(pool, source));
120 break;
121
122 case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
123 r = asprintf(&s, _("nothing provides %s needed by %s"),
124 pakfire_dep2str(problem->pakfire, dep), pool_solvid2str(pool, source));
125 break;
126
127 case SOLVER_RULE_RPM_SAME_NAME:
128 r = asprintf(&s, _("cannot install both %s and %s"),
129 pool_solvid2str(pool, source), pool_solvid2str(pool, target));
130 break;
131
132 case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
133 r = asprintf(&s, _("package %s conflicts with %s provided by %s"),
134 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep),
135 pool_solvid2str(pool, target));
136 break;
137
138 case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
139 r = asprintf(&s, _("package %s obsoletes %s provided by %s"),
140 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep),
141 pool_solvid2str(pool, target));
142 break;
143
144 case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES:
145 r = asprintf(&s, _("installed package %s obsoletes %s provided by %s"),
146 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep),
147 pool_solvid2str(pool, target));
148 break;
149
150 case SOLVER_RULE_RPM_IMPLICIT_OBSOLETES:
151 r = asprintf(&s, _("package %s implicitely obsoletes %s provided by %s"),
152 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep),
153 pool_solvid2str(pool, target));
154 break;
155
156 case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
157 r = asprintf(&s, _("package %s requires %s, but none of the providers can be installed"),
158 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep));
159 break;
160
161 case SOLVER_RULE_RPM_SELF_CONFLICT:
162 r = asprintf(&s, _("package %s conflicts with %s provided by itself"),
163 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep));
164 break;
165
166 case SOLVER_RULE_YUMOBS:
167 r = asprintf(&s, _("both package %s and %s obsolete %s"),
168 pool_solvid2str(pool, source), pool_solvid2str(pool, target),
169 pakfire_dep2str(problem->pakfire, dep));
170 break;
171
172 case SOLVER_RULE_BLACK:
173 r = asprintf(&s, _("package %s can only be installed by direct request"),
174 pool_solvid2str(pool, source));
175 break;
176
177 case SOLVER_RULE_PKG_CONSTRAINS:
178 r = asprintf(&s, _("package %s has constraint %s conflicting with %s"),
179 pool_solvid2str(pool, source), pakfire_dep2str(problem->pakfire, dep),
180 pool_solvid2str(pool, target));
181 break;
182
183 default:
184 r = asprintf(&s, _("bad rule type"));
185 break;
186 }
187
188 // Return nothing if asprintf failed
189 if (r < 0)
190 return NULL;
191
192 return s;
193 }
194
195 int pakfire_problem_create(struct pakfire_problem** problem,
196 struct pakfire* pakfire, struct pakfire_transaction* transaction, Id id) {
197 struct pakfire_problem* p = calloc(1, sizeof(*p));
198 if (!p)
199 return 1;
200
201 p->pakfire = pakfire_ref(pakfire);
202 p->nrefs = 1;
203
204 p->transaction = pakfire_transaction_ref(transaction);
205 p->id = id;
206
207 // Fetch a reference to the solver
208 p->solver = pakfire_transaction_get_solver(transaction);
209
210 *problem = p;
211 return 0;
212 }
213
214 PAKFIRE_EXPORT struct pakfire_problem* pakfire_problem_ref(struct pakfire_problem* problem) {
215 problem->nrefs++;
216
217 return problem;
218 }
219
220 static void pakfire_problem_free(struct pakfire_problem* problem) {
221 if (problem->transaction)
222 pakfire_transaction_unref(problem->transaction);
223 if (problem->string)
224 free(problem->string);
225 pakfire_unref(problem->pakfire);
226 free(problem);
227 }
228
229 PAKFIRE_EXPORT struct pakfire_problem* pakfire_problem_unref(struct pakfire_problem* problem) {
230 if (--problem->nrefs > 0)
231 return problem;
232
233 pakfire_problem_free(problem);
234 return NULL;
235 }
236
237 struct pakfire* pakfire_problem_get_pakfire(struct pakfire_problem* problem) {
238 return pakfire_ref(problem->pakfire);
239 }
240
241 PAKFIRE_EXPORT const char* pakfire_problem_to_string(struct pakfire_problem* problem) {
242 if (!problem->string)
243 problem->string = pakfire_problem_make_string(problem);
244
245 return problem->string;
246 }
247
248 Id pakfire_problem_get_id(struct pakfire_problem* problem) {
249 return problem->id;
250 }
251
252 struct pakfire_transaction* pakfire_problem_get_transaction(struct pakfire_problem* problem) {
253 return pakfire_transaction_ref(problem->transaction);
254 }
255
256 PAKFIRE_EXPORT struct pakfire_solution** pakfire_problem_get_solutions(
257 struct pakfire_problem* problem) {
258 struct pakfire_solution** solutions = NULL;
259 struct pakfire_solution* solution = NULL;
260 unsigned int count = 0;
261 Id id = ID_NULL;
262 int r;
263
264 // Fetch how many solutions we have
265 count = solver_solution_count(problem->solver, problem->id);
266 if (!count)
267 return NULL;
268
269 // Allocate some space
270 solutions = calloc(count + 1, sizeof(*solutions));
271 if (!solutions) {
272 r = -errno;
273 goto ERROR;
274 }
275
276 for (unsigned int i = 0; i < count; i++) {
277 id = solver_next_solution(problem->solver, problem->id, id);
278 if (!id)
279 break;
280
281 // Create a new solution
282 r = pakfire_solution_create(&solution, problem->pakfire, problem, id);
283 if (r)
284 goto ERROR;
285
286 // Store the reference
287 solutions[i] = solution;
288 }
289
290 return solutions;
291
292 ERROR:
293 ERROR_ERRNO(problem->pakfire, r, "Could not import solutions: %m\n");
294
295 if (solutions) {
296 for (struct pakfire_solution** s = solutions; *s; s++)
297 pakfire_solution_unref(*s);
298
299 free(solutions);
300 }
301
302 return NULL;
303 }