]> git.saurik.com Git - apt.git/blob - apt-pkg/upgrade.cc
provide a constexpr char[] overload for APT::StringView
[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 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 bool pkgDistUpgrade(pkgDepCache &Cache)
124 {
125 return pkgDistUpgrade(Cache, NULL);
126 }
127 /*}}}*/
128 // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/
129 static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
130 {
131 std::string const solver = _config->Find("APT::Solver", "internal");
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"));
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 }
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;
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 */
175 static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const Progress)
176 {
177 std::string const solver = _config->Find("APT::Solver", "internal");
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"));
183
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
205 if (Progress != NULL)
206 Progress->Progress(10);
207
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
213 if (Progress != NULL)
214 Progress->Progress(50);
215
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
221 if (Progress != NULL)
222 Progress->Progress(60);
223
224 // resolve remaining issues via keep
225 bool const success = Fix.ResolveByKeep(Progress);
226 if (Progress != NULL)
227 Progress->Done();
228 return success;
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 */
236 static bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
237 {
238 return pkgAllUpgradeNoNewPackages(Cache, Progress);
239 }
240 bool pkgAllUpgrade(pkgDepCache &Cache)
241 {
242 return pkgAllUpgrade(Cache, NULL);
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. */
250 bool 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 {
275 // If keep didn't actually do anything then there was no change..
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 /*}}}*/
290 // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/
291 bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress)
292 {
293 APT_IGNORE_DEPRECATED_PUSH
294 if (mode == ALLOW_EVERYTHING)
295 return pkgDistUpgrade(Cache, Progress);
296 else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
297 return pkgAllUpgradeWithNewPackages(Cache, Progress);
298 else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
299 return pkgAllUpgradeNoNewPackages(Cache, Progress);
300 else
301 _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
302 APT_IGNORE_DEPRECATED_POP
303 return false;
304 }
305 /*}}}*/