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