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