]> git.saurik.com Git - apt.git/blob - apt-pkg/upgrade.cc
Merge commit 'e2073b0276226b625897ef475f225bf8f508719e' as 'triehash'
[apt.git] / apt-pkg / upgrade.cc
1 // Include Files /*{{{*/
2 #include <config.h>
3
4 #include <apt-pkg/algorithms.h>
5 #include <apt-pkg/configuration.h>
6 #include <apt-pkg/edsp.h>
7 #include <apt-pkg/error.h>
8 #include <apt-pkg/progress.h>
9 #include <apt-pkg/upgrade.h>
10 #include <apt-pkg/depcache.h>
11 #include <apt-pkg/pkgcache.h>
12 #include <apt-pkg/cacheiterators.h>
13
14 #include <string>
15
16 #include <apti18n.h>
17 /*}}}*/
18
19 // DistUpgrade - Distribution upgrade /*{{{*/
20 // ---------------------------------------------------------------------
21 /* This autoinstalls every package and then force installs every
22 pre-existing package. This creates the initial set of conditions which
23 most likely contain problems because too many things were installed.
24
25 The problem resolver is used to resolve the problems.
26 */
27 static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
28 {
29 std::string const solver = _config->Find("APT::Solver", "internal");
30 auto const ret = EDSP::ResolveExternal(solver.c_str(), Cache, EDSP::Request::UPGRADE_ALL, Progress);
31 if (solver != "internal")
32 return ret;
33
34 if (Progress != NULL)
35 Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
36
37 pkgDepCache::ActionGroup group(Cache);
38
39 /* Upgrade all installed packages first without autoinst to help the resolver
40 in versioned or-groups to upgrade the old solver instead of installing
41 a new one (if the old solver is not the first one [anymore]) */
42 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
43 if (I->CurrentVer != 0)
44 Cache.MarkInstall(I, false, 0, false);
45
46 if (Progress != NULL)
47 Progress->Progress(10);
48
49 /* Auto upgrade all installed packages, this provides the basis
50 for the installation */
51 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
52 if (I->CurrentVer != 0)
53 Cache.MarkInstall(I, true, 0, false);
54
55 if (Progress != NULL)
56 Progress->Progress(50);
57
58 /* Now, install each essential package which is not installed
59 (and not provided by another package in the same name group) */
60 std::string essential = _config->Find("pkgCacheGen::Essential", "all");
61 if (essential == "all")
62 {
63 for (pkgCache::GrpIterator G = Cache.GrpBegin(); G.end() == false; ++G)
64 {
65 bool isEssential = false;
66 bool instEssential = false;
67 for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P))
68 {
69 if ((P->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
70 continue;
71 isEssential = true;
72 if (Cache[P].Install() == true)
73 {
74 instEssential = true;
75 break;
76 }
77 }
78 if (isEssential == false || instEssential == true)
79 continue;
80 pkgCache::PkgIterator P = G.FindPreferredPkg();
81 Cache.MarkInstall(P, true, 0, false);
82 }
83 }
84 else if (essential != "none")
85 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
86 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
87 Cache.MarkInstall(I, true, 0, false);
88
89 if (Progress != NULL)
90 Progress->Progress(55);
91
92 /* We do it again over all previously installed packages to force
93 conflict resolution on them all. */
94 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
95 if (I->CurrentVer != 0)
96 Cache.MarkInstall(I, false, 0, false);
97
98 if (Progress != NULL)
99 Progress->Progress(65);
100
101 pkgProblemResolver Fix(&Cache);
102
103 if (Progress != NULL)
104 Progress->Progress(95);
105
106 // Hold back held packages.
107 if (_config->FindB("APT::Ignore-Hold",false) == false)
108 {
109 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
110 {
111 if (I->SelectedState == pkgCache::State::Hold)
112 {
113 Fix.Protect(I);
114 Cache.MarkKeep(I, false, false);
115 }
116 }
117 }
118
119 bool const success = Fix.ResolveInternal(false);
120 if (Progress != NULL)
121 Progress->Done();
122 return success;
123 }
124 bool pkgDistUpgrade(pkgDepCache &Cache)
125 {
126 return pkgDistUpgrade(Cache, NULL);
127 }
128 /*}}}*/
129 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/
130 static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
131 {
132 std::string const solver = _config->Find("APT::Solver", "internal");
133 constexpr auto flags = EDSP::Request::UPGRADE_ALL | EDSP::Request::FORBID_NEW_INSTALL | EDSP::Request::FORBID_REMOVE;
134 auto const ret = EDSP::ResolveExternal(solver.c_str(), Cache, flags, Progress);
135 if (solver != "internal")
136 return ret;
137
138 if (Progress != NULL)
139 Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
140
141 pkgDepCache::ActionGroup group(Cache);
142 pkgProblemResolver Fix(&Cache);
143
144 // Upgrade all installed packages
145 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
146 {
147 if (Cache[I].Install() == true)
148 Fix.Protect(I);
149
150 if (_config->FindB("APT::Ignore-Hold",false) == false)
151 if (I->SelectedState == pkgCache::State::Hold)
152 continue;
153
154 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
155 Cache.MarkInstall(I, false, 0, false);
156 }
157
158 if (Progress != NULL)
159 Progress->Progress(50);
160
161 // resolve remaining issues via keep
162 bool const success = Fix.ResolveByKeepInternal();
163 if (Progress != NULL)
164 Progress->Done();
165 return success;
166 }
167 /*}}}*/
168 // AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/
169 // ---------------------------------------------------------------------
170 /* Right now the system must be consistent before this can be called.
171 * Upgrade as much as possible without deleting anything (useful for
172 * stable systems)
173 */
174 static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
175 {
176 std::string const solver = _config->Find("APT::Solver", "internal");
177 constexpr auto flags = EDSP::Request::UPGRADE_ALL | EDSP::Request::FORBID_REMOVE;
178 auto const ret = EDSP::ResolveExternal(solver.c_str(), Cache, flags, Progress);
179 if (solver != "internal")
180 return ret;
181
182 if (Progress != NULL)
183 Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
184
185 pkgDepCache::ActionGroup group(Cache);
186 pkgProblemResolver Fix(&Cache);
187
188 // provide the initial set of stuff we want to upgrade by marking
189 // all upgradable packages for upgrade
190 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
191 {
192 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
193 {
194 if (_config->FindB("APT::Ignore-Hold",false) == false)
195 if (I->SelectedState == pkgCache::State::Hold)
196 continue;
197
198 Cache.MarkInstall(I, false, 0, false);
199 }
200 }
201
202 if (Progress != NULL)
203 Progress->Progress(10);
204
205 // then let auto-install loose
206 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
207 if (Cache[I].Install())
208 Cache.MarkInstall(I, true, 0, false);
209
210 if (Progress != NULL)
211 Progress->Progress(50);
212
213 // ... but it may remove stuff, we we need to clean up afterwards again
214 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
215 if (Cache[I].Delete() == true)
216 Cache.MarkKeep(I, false, false);
217
218 if (Progress != NULL)
219 Progress->Progress(60);
220
221 // resolve remaining issues via keep
222 bool const success = Fix.ResolveByKeepInternal();
223 if (Progress != NULL)
224 Progress->Done();
225 return success;
226 }
227 /*}}}*/
228 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
229 // ---------------------------------------------------------------------
230 /* Right now the system must be consistent before this can be called.
231 It also will not change packages marked for install, it only tries
232 to install packages not marked for install */
233 static bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
234 {
235 return pkgAllUpgradeNoNewPackages(Cache, Progress);
236 }
237 bool pkgAllUpgrade(pkgDepCache &Cache)
238 {
239 return pkgAllUpgrade(Cache, NULL);
240 }
241 /*}}}*/
242 // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
243 // ---------------------------------------------------------------------
244 /* This simply goes over the entire set of packages and tries to keep
245 each package marked for upgrade. If a conflict is generated then
246 the package is restored. */
247 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
248 {
249 pkgDepCache::ActionGroup group(Cache);
250
251 if (Cache.BrokenCount() != 0)
252 return false;
253
254 // We loop for 10 tries to get the minimal set size.
255 bool Change = false;
256 unsigned int Count = 0;
257 do
258 {
259 Change = false;
260 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
261 {
262 // Not interesting
263 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
264 continue;
265
266 // Keep it and see if that is OK
267 Cache.MarkKeep(I, false, false);
268 if (Cache.BrokenCount() != 0)
269 Cache.MarkInstall(I, false, 0, false);
270 else
271 {
272 // If keep didn't actually do anything then there was no change..
273 if (Cache[I].Upgrade() == false)
274 Change = true;
275 }
276 }
277 ++Count;
278 }
279 while (Change == true && Count < 10);
280
281 if (Cache.BrokenCount() != 0)
282 return _error->Error("Internal Error in pkgMinimizeUpgrade");
283
284 return true;
285 }
286 /*}}}*/
287 // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/
288 bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress)
289 {
290 APT_IGNORE_DEPRECATED_PUSH
291 if (mode == ALLOW_EVERYTHING)
292 return pkgDistUpgrade(Cache, Progress);
293 else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
294 return pkgAllUpgradeWithNewPackages(Cache, Progress);
295 else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
296 return pkgAllUpgradeNoNewPackages(Cache, Progress);
297 else
298 _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
299 APT_IGNORE_DEPRECATED_POP
300 return false;
301 }
302 /*}}}*/