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