]> git.saurik.com Git - apt.git/blob - apt-pkg/upgrade.cc
Merge branch 'debian/sid' into debian/experimental
[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 bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
28 {
29 std::string const solver = _config->Find("APT::Solver", "internal");
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"));
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
45 if (Progress != NULL)
46 Progress->Progress(10);
47
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
54 if (Progress != NULL)
55 Progress->Progress(50);
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 if (Progress != NULL)
89 Progress->Progress(55);
90
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
97 if (Progress != NULL)
98 Progress->Progress(65);
99
100 pkgProblemResolver Fix(&Cache);
101
102 if (Progress != NULL)
103 Progress->Progress(95);
104
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 }
117
118 bool const success = Fix.Resolve(false, Progress);
119 if (Progress != NULL)
120 Progress->Done();
121 return success;
122 }
123 /*}}}*/
124 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/
125 static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
126 {
127 std::string const solver = _config->Find("APT::Solver", "internal");
128 if (solver != "internal")
129 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
130
131 if (Progress != NULL)
132 Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
133
134 pkgDepCache::ActionGroup group(Cache);
135
136 pkgProblemResolver Fix(&Cache);
137
138 if (Cache.BrokenCount() != 0)
139 return false;
140
141 // Upgrade all installed packages
142 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
143 {
144 if (Cache[I].Install() == true)
145 Fix.Protect(I);
146
147 if (_config->FindB("APT::Ignore-Hold",false) == false)
148 if (I->SelectedState == pkgCache::State::Hold)
149 continue;
150
151 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
152 Cache.MarkInstall(I, false, 0, false);
153 }
154
155 if (Progress != NULL)
156 Progress->Progress(50);
157
158 // resolve remaining issues via keep
159 bool const success = Fix.ResolveByKeep(Progress);
160 if (Progress != NULL)
161 Progress->Done();
162 return success;
163 }
164 /*}}}*/
165 // AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/
166 // ---------------------------------------------------------------------
167 /* Right now the system must be consistent before this can be called.
168 * Upgrade as much as possible without deleting anything (useful for
169 * stable systems)
170 */
171 static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
172 {
173 std::string const solver = _config->Find("APT::Solver", "internal");
174 if (solver != "internal")
175 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
176
177 if (Progress != NULL)
178 Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
179
180 pkgDepCache::ActionGroup group(Cache);
181
182 pkgProblemResolver Fix(&Cache);
183
184 if (Cache.BrokenCount() != 0)
185 return false;
186
187 // provide the initial set of stuff we want to upgrade by marking
188 // all upgradable packages for upgrade
189 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
190 {
191 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
192 {
193 if (_config->FindB("APT::Ignore-Hold",false) == false)
194 if (I->SelectedState == pkgCache::State::Hold)
195 continue;
196
197 Cache.MarkInstall(I, false, 0, false);
198 }
199 }
200
201 if (Progress != NULL)
202 Progress->Progress(10);
203
204 // then let auto-install loose
205 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
206 if (Cache[I].Install())
207 Cache.MarkInstall(I, true, 0, false);
208
209 if (Progress != NULL)
210 Progress->Progress(50);
211
212 // ... but it may remove stuff, we we need to clean up afterwards again
213 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
214 if (Cache[I].Delete() == true)
215 Cache.MarkKeep(I, false, false);
216
217 if (Progress != NULL)
218 Progress->Progress(60);
219
220 // resolve remaining issues via keep
221 bool const success = Fix.ResolveByKeep(Progress);
222 if (Progress != NULL)
223 Progress->Done();
224 return success;
225 }
226 /*}}}*/
227 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
228 // ---------------------------------------------------------------------
229 /* Right now the system must be consistent before this can be called.
230 It also will not change packages marked for install, it only tries
231 to install packages not marked for install */
232 bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
233 {
234 return pkgAllUpgradeNoNewPackages(Cache, Progress);
235 }
236 /*}}}*/
237 // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
238 // ---------------------------------------------------------------------
239 /* This simply goes over the entire set of packages and tries to keep
240 each package marked for upgrade. If a conflict is generated then
241 the package is restored. */
242 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
243 {
244 pkgDepCache::ActionGroup group(Cache);
245
246 if (Cache.BrokenCount() != 0)
247 return false;
248
249 // We loop for 10 tries to get the minimal set size.
250 bool Change = false;
251 unsigned int Count = 0;
252 do
253 {
254 Change = false;
255 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
256 {
257 // Not interesting
258 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
259 continue;
260
261 // Keep it and see if that is OK
262 Cache.MarkKeep(I, false, false);
263 if (Cache.BrokenCount() != 0)
264 Cache.MarkInstall(I, false, 0, false);
265 else
266 {
267 // If keep didn't actually do anything then there was no change..
268 if (Cache[I].Upgrade() == false)
269 Change = true;
270 }
271 }
272 ++Count;
273 }
274 while (Change == true && Count < 10);
275
276 if (Cache.BrokenCount() != 0)
277 return _error->Error("Internal Error in pkgMinimizeUpgrade");
278
279 return true;
280 }
281 /*}}}*/
282 // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/
283 bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress)
284 {
285 #if __GNUC__ >= 4
286 // the deprecated methods will become our privates, so that is fine
287 #pragma GCC diagnostic push
288 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
289 #endif
290 if (mode == ALLOW_EVERYTHING)
291 return pkgDistUpgrade(Cache, Progress);
292 else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
293 return pkgAllUpgradeWithNewPackages(Cache, Progress);
294 else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
295 return pkgAllUpgradeNoNewPackages(Cache, Progress);
296 else
297 _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
298 #if __GNUC__ >= 4
299 #pragma GCC diagnostic pop
300 #endif
301 return false;
302 }
303 /*}}}*/