1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * Copyright (C) 2013-2015 Richard Hughes <richard@hughsie.com>
4 *
5 * Most of this code was taken from Zif, libzif/zif-transaction.c
6 *
7 * Licensed under the GNU Lesser General Public License Version 2.1
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or(at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /**
25 * SECTION:dnf-goal
26 * @short_description: Helper methods for dealing with hawkey goals.
27 * @include: libdnf.h
28 * @stability: Unstable
29 *
30 * These methods make it easier to deal with hawkey goals.
31 */
32
33
34 #include <glib.h>
35
36 #include "catch-error.hpp"
37 #include "hy-util.h"
38 #include "hy-goal-private.hpp"
39 #include "dnf-goal.h"
40 #include "dnf-package.h"
41 #include "hy-packageset-private.hpp"
42 #include "hy-iutil-private.hpp"
43 #include "dnf-context.hpp"
44 #include "dnf-sack-private.hpp"
45 #include "dnf-utils.h"
46 #include "utils/bgettext/bgettext-lib.h"
47 #include "../goal/Goal.hpp"
48
49 #include <vector>
50
51 /**
52 * dnf_goal_depsolve:
53 * @goal: a #HyGoal.
54 * @flags: some #DnfGoalActions to enable.
55 * @error: a #GError or %NULL
56 *
57 * Returns: %TRUE if depsolve is successful.
58 *
59 * Since: 0.7.0
60 */
61 gboolean
dnf_goal_depsolve(HyGoal goal,DnfGoalActions flags,GError ** error)62 dnf_goal_depsolve(HyGoal goal, DnfGoalActions flags, GError **error) try
63 {
64 gint cnt;
65 gint j;
66 gint rc;
67 g_autoptr(GString) string = NULL;
68
69 DnfSack * sack = hy_goal_get_sack(goal);
70
71 libdnf::Query query(sack);
72 const auto & protected_packages = libdnf::getGlobalMainConfig().protected_packages().getValue();
73 std::vector<const char *> cprotected_packages;
74 cprotected_packages.reserve(protected_packages.size() + 1);
75 for (const auto & package : protected_packages) {
76 cprotected_packages.push_back(package.c_str());
77 }
78 cprotected_packages.push_back(nullptr);
79 query.addFilter(HY_PKG_NAME, HY_EQ, cprotected_packages.data());
80 auto pkgset = *query.runSet();
81 goal->addProtected(pkgset);
82
83 rc = hy_goal_run_flags(goal, flags);
84 if (rc) {
85 string = g_string_new(_("Could not depsolve transaction; "));
86 cnt = hy_goal_count_problems(goal);
87 g_string_append_printf(string, P_("%i problem detected:\n", "%i problems detected:\n", cnt),
88 cnt);
89 for (j = 0; j < cnt; j++) {
90 auto tmp = goal->describeProblemRules(j, true);
91 bool first = true;
92 for (auto & iter: tmp) {
93 if (first) {
94 if (cnt != 1) {
95 g_string_append_printf(string, _(" Problem %1$i: %2$s\n"), j + 1, iter.c_str());
96 } else {
97 g_string_append_printf(string, _(" Problem: %s\n"), iter.c_str());
98 }
99 first = false;
100 } else {
101 g_string_append_printf(string, " - %s\n", iter.c_str());
102 }
103 }
104 }
105 g_string_truncate(string, string->len - 1);
106 g_set_error_literal(error,
107 DNF_ERROR,
108 DNF_ERROR_PACKAGE_CONFLICTS,
109 string->str);
110 return FALSE;
111 }
112
113 /* anything to do? */
114 if (hy_goal_req_length(goal) == 0) {
115 g_set_error_literal(error,
116 DNF_ERROR,
117 DNF_ERROR_NO_PACKAGES_TO_UPDATE,
118 "The transaction was empty");
119 return FALSE;
120 }
121 auto moduleContainer = dnf_sack_get_module_container(sack);
122 if (moduleContainer) {
123 auto installSet = goal->listInstalls();
124 auto modulesToEnable = requiresModuleEnablement(sack, &installSet);
125 for (auto module: modulesToEnable) {
126 moduleContainer->enable(module->getName(), module->getStream());
127 }
128 }
129 return TRUE;
130 } CATCH_TO_GERROR(FALSE)
131
132 /**
133 * dnf_goal_get_packages:
134 */
135 GPtrArray *
136 dnf_goal_get_packages(HyGoal goal, ...)
137 {
138 GPtrArray *array;
139 DnfPackage *pkg;
140 gint info_tmp;
141 guint i;
142 guint j;
143 va_list args;
144
145 /* process the valist */
146 va_start(args, goal);
147 array = g_ptr_array_new_with_free_func((GDestroyNotify) g_object_unref);
148 for (j = 0;; j++) {
149 GPtrArray *pkglist = NULL;
150 info_tmp = va_arg(args, gint);
151 if (info_tmp == -1)
152 break;
153 switch(info_tmp) {
154 case DNF_PACKAGE_INFO_REMOVE:
155 pkglist = hy_goal_list_erasures(goal, NULL);
156 for (i = 0; i < pkglist->len; i++) {
157 pkg = (DnfPackage*)g_ptr_array_index (pkglist, i);
158 dnf_package_set_action(pkg, DNF_STATE_ACTION_REMOVE);
159 g_ptr_array_add(array, g_object_ref(pkg));
160 }
161 break;
162 case DNF_PACKAGE_INFO_INSTALL:
163 pkglist = hy_goal_list_installs(goal, NULL);
164 for (i = 0; i < pkglist->len; i++) {
165 pkg = (DnfPackage*)g_ptr_array_index (pkglist, i);
166 dnf_package_set_action(pkg, DNF_STATE_ACTION_INSTALL);
167 g_ptr_array_add(array, g_object_ref(pkg));
168 }
169 break;
170 case DNF_PACKAGE_INFO_OBSOLETE:
171 pkglist = hy_goal_list_obsoleted(goal, NULL);
172 for (i = 0; i < pkglist->len; i++) {
173 pkg = (DnfPackage*)g_ptr_array_index (pkglist, i);
174 dnf_package_set_action(pkg, DNF_STATE_ACTION_OBSOLETE);
175 g_ptr_array_add(array, g_object_ref(pkg));
176 }
177 break;
178 case DNF_PACKAGE_INFO_REINSTALL:
179 pkglist = hy_goal_list_reinstalls(goal, NULL);
180 for (i = 0; i < pkglist->len; i++) {
181 pkg = (DnfPackage*)g_ptr_array_index (pkglist, i);
182 dnf_package_set_action(pkg, DNF_STATE_ACTION_REINSTALL);
183 g_ptr_array_add(array, g_object_ref(pkg));
184 }
185 break;
186 case DNF_PACKAGE_INFO_UPDATE:
187 pkglist = hy_goal_list_upgrades(goal, NULL);
188 for (i = 0; i < pkglist->len; i++) {
189 pkg = (DnfPackage*)g_ptr_array_index (pkglist, i);
190 dnf_package_set_action(pkg, DNF_STATE_ACTION_UPDATE);
191 g_ptr_array_add(array, g_object_ref(pkg));
192 }
193 break;
194 case DNF_PACKAGE_INFO_DOWNGRADE:
195 pkglist = hy_goal_list_downgrades(goal, NULL);
196 for (i = 0; i < pkglist->len; i++) {
197 pkg = (DnfPackage*)g_ptr_array_index (pkglist, i);
198 dnf_package_set_action(pkg, DNF_STATE_ACTION_DOWNGRADE);
199 g_ptr_array_add(array, g_object_ref(pkg));
200 }
201 break;
202 default:
203 g_assert_not_reached();
204 }
205 g_ptr_array_unref(pkglist);
206 }
207 va_end(args);
208 return array;
209 }
210
211 /**
212 * dnf_goal_add_protected:
213 * @goal: a #HyGoal.
214 * @pset: a #DnfPackageSet that would be added to the protected packages.
215 *
216 * Since: 0.7.0
217 */
218 void
dnf_goal_add_protected(HyGoal goal,DnfPackageSet * pset)219 dnf_goal_add_protected(HyGoal goal, DnfPackageSet *pset)
220 {
221 goal->addProtected(*pset);
222 }
223
224 /**
225 * dnf_goal_set_protected:
226 * @goal: a #HyGoal.
227 * @pset: a #DnfPackageSet of protected packages (the previous setup will be overridden).
228 *
229 * Since: 0.7.0
230 */
231 void
dnf_goal_set_protected(HyGoal goal,DnfPackageSet * pset)232 dnf_goal_set_protected(HyGoal goal, DnfPackageSet *pset)
233 {
234 goal->setProtected(*pset);
235 }
236