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