]> git.saurik.com Git - apt.git/blob - apt-pkg/upgrade.cc
do not do the same looping twice
[apt.git] / apt-pkg / upgrade.cc
1
2 // Include Files /*{{{*/
3 #include <config.h>
4
5 #include <apt-pkg/algorithms.h>
6 #include <apt-pkg/upgrade.h>
7 #include <apt-pkg/error.h>
8 #include <apt-pkg/configuration.h>
9 #include <apt-pkg/version.h>
10 #include <apt-pkg/sptr.h>
11 #include <apt-pkg/acquire-item.h>
12 #include <apt-pkg/edsp.h>
13 #include <apt-pkg/sourcelist.h>
14 #include <apt-pkg/fileutl.h>
15 #include <apt-pkg/progress.h>
16
17 #include <sys/types.h>
18 #include <cstdlib>
19 #include <algorithm>
20 #include <iostream>
21 #include <stdio.h>
22
23 #include <apti18n.h>
24 /*}}}*/
25
26 // DistUpgrade - Distribution upgrade /*{{{*/
27 // ---------------------------------------------------------------------
28 /* This autoinstalls every package and then force installs every
29 pre-existing package. This creates the initial set of conditions which
30 most likely contain problems because too many things were installed.
31
32 The problem resolver is used to resolve the problems.
33 */
34 bool pkgDistUpgrade(pkgDepCache &Cache)
35 {
36 std::string const solver = _config->Find("APT::Solver", "internal");
37 if (solver != "internal") {
38 OpTextProgress Prog(*_config);
39 return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog);
40 }
41
42 pkgDepCache::ActionGroup group(Cache);
43
44 /* Upgrade all installed packages first without autoinst to help the resolver
45 in versioned or-groups to upgrade the old solver instead of installing
46 a new one (if the old solver is not the first one [anymore]) */
47 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
48 if (I->CurrentVer != 0)
49 Cache.MarkInstall(I, false, 0, false);
50
51 /* Auto upgrade all installed packages, this provides the basis
52 for the installation */
53 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
54 if (I->CurrentVer != 0)
55 Cache.MarkInstall(I, true, 0, false);
56
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);
87
88 /* We do it again over all previously installed packages to force
89 conflict resolution on them all. */
90 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
91 if (I->CurrentVer != 0)
92 Cache.MarkInstall(I, false, 0, false);
93
94 pkgProblemResolver Fix(&Cache);
95
96 // Hold back held packages.
97 if (_config->FindB("APT::Ignore-Hold",false) == false)
98 {
99 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
100 {
101 if (I->SelectedState == pkgCache::State::Hold)
102 {
103 Fix.Protect(I);
104 Cache.MarkKeep(I, false, false);
105 }
106 }
107 }
108
109 return Fix.Resolve();
110 }
111 /*}}}*/
112 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/
113 static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
114 {
115 std::string const solver = _config->Find("APT::Solver", "internal");
116 if (solver != "internal") {
117 OpTextProgress Prog(*_config);
118 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
119 }
120
121 pkgDepCache::ActionGroup group(Cache);
122
123 pkgProblemResolver Fix(&Cache);
124
125 if (Cache.BrokenCount() != 0)
126 return false;
127
128 // Upgrade all installed packages
129 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
130 {
131 if (Cache[I].Install() == true)
132 Fix.Protect(I);
133
134 if (_config->FindB("APT::Ignore-Hold",false) == false)
135 if (I->SelectedState == pkgCache::State::Hold)
136 continue;
137
138 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
139 Cache.MarkInstall(I, false, 0, false);
140 }
141
142 return Fix.ResolveByKeep();
143 }
144 /*}}}*/
145 // AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/
146 // ---------------------------------------------------------------------
147 /* Right now the system must be consistent before this can be called.
148 * Upgrade as much as possible without deleting anything (useful for
149 * stable systems)
150 */
151 static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
152 {
153 pkgDepCache::ActionGroup group(Cache);
154
155 pkgProblemResolver Fix(&Cache);
156
157 if (Cache.BrokenCount() != 0)
158 return false;
159
160 // provide the initial set of stuff we want to upgrade by marking
161 // all upgradable packages for upgrade
162 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
163 {
164 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
165 {
166 if (_config->FindB("APT::Ignore-Hold",false) == false)
167 if (I->SelectedState == pkgCache::State::Hold)
168 continue;
169
170 Cache.MarkInstall(I, false, 0, false);
171 }
172 }
173
174 // then let auto-install loose
175 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
176 if (Cache[I].Install())
177 Cache.MarkInstall(I, true, 0, false);
178
179 // ... but it may remove stuff, we we need to clean up afterwards again
180 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
181 if (Cache[I].Delete() == true)
182 Cache.MarkKeep(I, false, false);
183
184 // resolve remaining issues via keep
185 return Fix.ResolveByKeep();
186 }
187 /*}}}*/
188 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
189 // ---------------------------------------------------------------------
190 /* Right now the system must be consistent before this can be called.
191 It also will not change packages marked for install, it only tries
192 to install packages not marked for install */
193 bool pkgAllUpgrade(pkgDepCache &Cache)
194 {
195 return pkgAllUpgradeNoNewPackages(Cache);
196 }
197 /*}}}*/
198 // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
199 // ---------------------------------------------------------------------
200 /* This simply goes over the entire set of packages and tries to keep
201 each package marked for upgrade. If a conflict is generated then
202 the package is restored. */
203 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
204 {
205 pkgDepCache::ActionGroup group(Cache);
206
207 if (Cache.BrokenCount() != 0)
208 return false;
209
210 // We loop for 10 tries to get the minimal set size.
211 bool Change = false;
212 unsigned int Count = 0;
213 do
214 {
215 Change = false;
216 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
217 {
218 // Not interesting
219 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
220 continue;
221
222 // Keep it and see if that is OK
223 Cache.MarkKeep(I, false, false);
224 if (Cache.BrokenCount() != 0)
225 Cache.MarkInstall(I, false, 0, false);
226 else
227 {
228 // If keep didn't actually do anything then there was no change..
229 if (Cache[I].Upgrade() == false)
230 Change = true;
231 }
232 }
233 ++Count;
234 }
235 while (Change == true && Count < 10);
236
237 if (Cache.BrokenCount() != 0)
238 return _error->Error("Internal Error in pkgMinimizeUpgrade");
239
240 return true;
241 }
242 /*}}}*/
243 // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/
244 bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode)
245 {
246 if (mode == 0)
247 {
248 return pkgDistUpgrade(Cache);
249 }
250 else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
251 {
252 return pkgAllUpgradeWithNewPackages(Cache);
253 }
254 else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
255 {
256 return pkgAllUpgradeNoNewPackages(Cache);
257 }
258 else
259 _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
260
261 return false;
262 }
263 /*}}}*/