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