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