]> git.saurik.com Git - apt.git/blame - apt-private/private-install.cc
add a simple unit test for acquire progress
[apt.git] / apt-private / private-install.cc
CommitLineData
b9179170
MV
1// Include Files /*{{{*/
2#include <config.h>
3
453b82a3 4#include <apt-pkg/acquire.h>
b9179170 5#include <apt-pkg/acquire-item.h>
453b82a3 6#include <apt-pkg/algorithms.h>
b9179170
MV
7#include <apt-pkg/cachefile.h>
8#include <apt-pkg/cacheset.h>
453b82a3
DK
9#include <apt-pkg/cmndline.h>
10#include <apt-pkg/depcache.h>
11#include <apt-pkg/error.h>
12#include <apt-pkg/fileutl.h>
b9179170 13#include <apt-pkg/pkgrecords.h>
453b82a3
DK
14#include <apt-pkg/pkgsystem.h>
15#include <apt-pkg/sptr.h>
16#include <apt-pkg/strutl.h>
17#include <apt-pkg/cacheiterators.h>
18#include <apt-pkg/configuration.h>
19#include <apt-pkg/macros.h>
20#include <apt-pkg/packagemanager.h>
21#include <apt-pkg/pkgcache.h>
172947cd 22#include <apt-pkg/upgrade.h>
b58f28d4 23#include <apt-pkg/install-progress.h>
0d29b9d4 24
453b82a3
DK
25#include <stdlib.h>
26#include <string.h>
453b82a3
DK
27#include <algorithm>
28#include <iostream>
29#include <set>
30#include <vector>
eafc5435 31#include <map>
b9179170 32
453b82a3
DK
33#include <apt-private/acqprogress.h>
34#include <apt-private/private-install.h>
35#include <apt-private/private-cachefile.h>
36#include <apt-private/private-cacheset.h>
37#include <apt-private/private-download.h>
38#include <apt-private/private-output.h>
b9179170
MV
39
40#include <apti18n.h>
41 /*}}}*/
453b82a3 42class pkgSourceList;
b9179170 43
b9179170
MV
44// InstallPackages - Actually download and install the packages /*{{{*/
45// ---------------------------------------------------------------------
46/* This displays the informative messages describing what is going to
47 happen and then calls the download routines */
48bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
49{
50 if (_config->FindB("APT::Get::Purge",false) == true)
51 {
52 pkgCache::PkgIterator I = Cache->PkgBegin();
53 for (; I.end() == false; ++I)
54 {
55 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
56 Cache->MarkDelete(I,true);
57 }
58 }
59
60 bool Fail = false;
61 bool Essential = false;
62
63 // Show all the various warning indicators
64 ShowDel(c1out,Cache);
65 ShowNew(c1out,Cache);
66 if (ShwKept == true)
67 ShowKept(c1out,Cache);
68 Fail |= !ShowHold(c1out,Cache);
69 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
70 ShowUpgraded(c1out,Cache);
71 Fail |= !ShowDowngraded(c1out,Cache);
72 if (_config->FindB("APT::Get::Download-Only",false) == false)
73 Essential = !ShowEssential(c1out,Cache);
74 Fail |= Essential;
75 Stats(c1out,Cache);
76
77 // Sanity check
78 if (Cache->BrokenCount() != 0)
79 {
80 ShowBroken(c1out,Cache,false);
81 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
82 }
83
84 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
85 Cache->BadCount() == 0)
86 return true;
87
88 // No remove flag
89 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
90 return _error->Error(_("Packages need to be removed but remove is disabled."));
91
92 // Run the simulator ..
93 if (_config->FindB("APT::Get::Simulate") == true)
94 {
95 pkgSimulate PM(Cache);
5e9458e2 96
ccf6bdb3 97#if APT_PKG_ABI >= 413
bd5f39b3 98 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
99 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
100 delete progress;
bd5f39b3
MV
101#else
102 int status_fd = _config->FindI("APT::Status-Fd",-1);
103 pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
104#endif
5e9458e2 105
b9179170
MV
106 if (Res == pkgPackageManager::Failed)
107 return false;
108 if (Res != pkgPackageManager::Completed)
109 return _error->Error(_("Internal error, Ordering didn't finish"));
110 return true;
111 }
112
113 // Create the text record parser
114 pkgRecords Recs(Cache);
115 if (_error->PendingError() == true)
116 return false;
117
118 // Create the download object
dfad5bee 119 AcqTextStatus Stat(std::cout, ScreenWidth,_config->FindI("quiet",0));
04a54261 120 pkgAcquire Fetcher(&Stat);
b9179170
MV
121 if (_config->FindB("APT::Get::Print-URIs", false) == true)
122 {
123 // force a hashsum for compatibility reasons
124 _config->CndSet("Acquire::ForceHash", "md5sum");
125 }
04a54261 126 else if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false)
b9179170
MV
127 return false;
128
129 // Read the source list
130 if (Cache.BuildSourceList() == false)
131 return false;
132 pkgSourceList *List = Cache.GetSourceList();
133
134 // Create the package manager and prepare to download
135 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
136 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
137 _error->PendingError() == true)
138 return false;
139
140 // Display statistics
141 unsigned long long FetchBytes = Fetcher.FetchNeeded();
142 unsigned long long FetchPBytes = Fetcher.PartialPresent();
143 unsigned long long DebBytes = Fetcher.TotalNeeded();
144 if (DebBytes != Cache->DebSize())
145 {
146 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
1166ea79 147 c0out << _("How odd... The sizes didn't match, email apt@packages.debian.org") << std::endl;
b9179170
MV
148 }
149
150 // Number of bytes
151 if (DebBytes != FetchBytes)
152 //TRANSLATOR: The required space between number and unit is already included
153 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
154 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
155 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
156 else if (DebBytes != 0)
157 //TRANSLATOR: The required space between number and unit is already included
158 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
159 ioprintf(c1out,_("Need to get %sB of archives.\n"),
160 SizeToStr(DebBytes).c_str());
161
162 // Size delta
163 if (Cache->UsrSize() >= 0)
164 //TRANSLATOR: The required space between number and unit is already included
165 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
166 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
167 SizeToStr(Cache->UsrSize()).c_str());
168 else
169 //TRANSLATOR: The required space between number and unit is already included
170 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
171 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
172 SizeToStr(-1*Cache->UsrSize()).c_str());
173
174 if (_error->PendingError() == true)
175 return false;
176
9c81f8de
DK
177 if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false)
178 return false;
179
b9179170
MV
180 // Fail safe check
181 if (_config->FindI("quiet",0) >= 2 ||
182 _config->FindB("APT::Get::Assume-Yes",false) == true)
183 {
184 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
185 return _error->Error(_("There are problems and -y was used without --force-yes"));
186 }
187
188 if (Essential == true && Safety == true)
189 {
190 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
191 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
192
193 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
194 // careful with hard to type or special characters (like non-breaking spaces)
195 const char *Prompt = _("Yes, do as I say!");
196 ioprintf(c2out,
197 _("You are about to do something potentially harmful.\n"
198 "To continue type in the phrase '%s'\n"
199 " ?] "),Prompt);
200 c2out << std::flush;
201 if (AnalPrompt(Prompt) == false)
202 {
203 c2out << _("Abort.") << std::endl;
204 exit(1);
205 }
206 }
207 else
208 {
209 // Prompt to continue
210 if (Ask == true || Fail == true)
211 {
212 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
213 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
214
215 if (_config->FindI("quiet",0) < 2 &&
216 _config->FindB("APT::Get::Assume-Yes",false) == false)
217 {
218 c2out << _("Do you want to continue?") << std::flush;
219 if (YnPrompt() == false)
220 {
221 c2out << _("Abort.") << std::endl;
222 exit(1);
223 }
224 }
225 }
226 }
227
228 // Just print out the uris an exit if the --print-uris flag was used
229 if (_config->FindB("APT::Get::Print-URIs") == true)
230 {
231 pkgAcquire::UriIterator I = Fetcher.UriBegin();
232 for (; I != Fetcher.UriEnd(); ++I)
ac69a4d8 233 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
b9179170
MV
234 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
235 return true;
236 }
237
866893a6 238 if (!CheckAuth(Fetcher, true))
b9179170
MV
239 return false;
240
241 /* Unlock the dpkg lock if we are not going to be doing an install
242 after. */
243 if (_config->FindB("APT::Get::Download-Only",false) == true)
244 _system->UnLock();
245
246 // Run it
247 while (1)
248 {
249 bool Transient = false;
250 if (_config->FindB("APT::Get::Download",true) == false)
251 {
252 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
253 {
254 if ((*I)->Local == true)
255 {
256 ++I;
257 continue;
258 }
259
260 // Close the item and check if it was found in cache
261 (*I)->Finished();
262 if ((*I)->Complete == false)
263 Transient = true;
264
265 // Clear it out of the fetch list
266 delete *I;
267 I = Fetcher.ItemsBegin();
268 }
269 }
b9179170 270
866893a6
DK
271 bool Failed = false;
272 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
273 return false;
b9179170
MV
274
275 /* If we are in no download mode and missing files and there were
276 'failures' then the user must specify -m. Furthermore, there
277 is no such thing as a transient error in no-download mode! */
278 if (Transient == true &&
279 _config->FindB("APT::Get::Download",true) == false)
280 {
281 Transient = false;
282 Failed = true;
283 }
284
285 if (_config->FindB("APT::Get::Download-Only",false) == true)
286 {
287 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
288 return _error->Error(_("Some files failed to download"));
289 c1out << _("Download complete and in download only mode") << std::endl;
290 return true;
291 }
292
293 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
294 {
295 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
296 }
297
298 if (Transient == true && Failed == true)
299 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
300
301 // Try to deal with missing package files
302 if (Failed == true && PM->FixMissing() == false)
303 {
304 c2out << _("Unable to correct missing packages.") << std::endl;
305 return _error->Error(_("Aborting install."));
306 }
307
308 _system->UnLock();
ccf6bdb3
DK
309
310#if APT_PKG_ABI >= 413
bd5f39b3 311 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
312 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
313 delete progress;
bd5f39b3
MV
314#else
315 int status_fd = _config->FindI("APT::Status-Fd", -1);
316 pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
317#endif
e6ad8031 318
b9179170
MV
319 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
320 return false;
321 if (Res == pkgPackageManager::Completed)
322 break;
323
324 // Reload the fetcher object and loop again for media swapping
325 Fetcher.Shutdown();
326 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
327 return false;
328
329 _system->Lock();
330 }
331
332 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
333 if (disappearedPkgs.empty() == true)
334 return true;
335
336 std::string disappear;
337 for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
338 d != disappearedPkgs.end(); ++d)
339 disappear.append(*d).append(" ");
340
341 ShowList(c1out, P_("The following package disappeared from your system as\n"
342 "all files have been overwritten by other packages:",
343 "The following packages disappeared from your system as\n"
344 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
345 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
346
347 return true;
348}
349 /*}}}*/
b9179170
MV
350// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
351// ---------------------------------------------------------------------
352/* Remove unused automatic packages */
c3ccac92 353static bool DoAutomaticRemove(CacheFile &Cache)
b9179170
MV
354{
355 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
356 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
357 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
358
359 pkgDepCache::ActionGroup group(*Cache);
360 if(Debug)
361 std::cout << "DoAutomaticRemove()" << std::endl;
362
363 if (doAutoRemove == true &&
364 _config->FindB("APT::Get::Remove",true) == false)
365 {
366 c1out << _("We are not supposed to delete stuff, can't start "
367 "AutoRemover") << std::endl;
368 return false;
369 }
370
371 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
372 bool smallList = (hideAutoRemove == false &&
373 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
374
375 unsigned long autoRemoveCount = 0;
376 APT::PackageSet tooMuch;
377 APT::PackageList autoRemoveList;
378 // look over the cache to see what can be removed
379 for (unsigned J = 0; J < Cache->Head().PackageCount; ++J)
380 {
381 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
382 if (Cache[Pkg].Garbage)
383 {
384 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
385 if(Debug)
386 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
387
388 if (doAutoRemove)
389 {
390 if(Pkg.CurrentVer() != 0 &&
391 Pkg->CurrentState != pkgCache::State::ConfigFiles)
392 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
393 else
394 Cache->MarkKeep(Pkg, false, false);
395 }
396 else
397 {
398 if (hideAutoRemove == false && Cache[Pkg].Delete() == false)
399 autoRemoveList.insert(Pkg);
400 // if the package is a new install and already garbage we don't need to
401 // install it in the first place, so nuke it instead of show it
402 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
403 {
404 if (Pkg.CandVersion() != 0)
405 tooMuch.insert(Pkg);
406 Cache->MarkDelete(Pkg, false, 0, false);
407 }
408 // only show stuff in the list that is not yet marked for removal
409 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
410 ++autoRemoveCount;
411 }
412 }
413 }
414
415 // we could have removed a new dependency of a garbage package,
416 // so check if a reverse depends is broken and if so install it again.
417 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
418 {
419 bool Changed;
420 do {
421 Changed = false;
422 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
3a7a206f 423 Pkg != tooMuch.end(); ++Pkg)
b9179170
MV
424 {
425 APT::PackageSet too;
426 too.insert(*Pkg);
427 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
428 Prv.end() == false; ++Prv)
429 too.insert(Prv.ParentPkg());
3a7a206f
DK
430 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
431 {
b9179170
MV
432 for (pkgCache::DepIterator R = P.RevDependsList();
433 R.end() == false; ++R)
434 {
435 if (R.IsNegative() == true ||
436 Cache->IsImportantDep(R) == false)
437 continue;
438 pkgCache::PkgIterator N = R.ParentPkg();
439 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
440 continue;
441 if (Debug == true)
442 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
443 Cache->MarkInstall(Pkg, false, 0, false);
444 if (hideAutoRemove == false)
445 ++autoRemoveCount;
446 tooMuch.erase(Pkg);
447 Changed = true;
448 break;
449 }
3a7a206f
DK
450 if (Changed == true)
451 break;
b9179170 452 }
3a7a206f
DK
453 if (Changed == true)
454 break;
b9179170
MV
455 }
456 } while (Changed == true);
457 }
458
459 std::string autoremovelist, autoremoveversions;
460 if (smallList == false && autoRemoveCount != 0)
461 {
462 for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg)
463 {
464 if (Cache[Pkg].Garbage == false)
465 continue;
466 autoremovelist += Pkg.FullName(true) + " ";
467 autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n";
468 }
469 }
470
471 // Now see if we had destroyed anything (if we had done anything)
472 if (Cache->BrokenCount() != 0)
473 {
474 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
475 "shouldn't happen. Please file a bug report against apt.") << std::endl;
476 c1out << std::endl;
477 c1out << _("The following information may help to resolve the situation:") << std::endl;
478 c1out << std::endl;
479 ShowBroken(c1out,Cache,false);
480
481 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
482 }
483
484 // if we don't remove them, we should show them!
485 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
486 {
487 if (smallList == false)
488 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
489 "The following packages were automatically installed and are no longer required:",
490 autoRemoveCount), autoremovelist, autoremoveversions);
491 else
492 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
493 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
494 c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl;
495 }
496 return true;
497}
498 /*}}}*/
ee0167c4 499// DoCacheManipulationFromCommandLine /*{{{*/
d8a8f9d7
MV
500static const unsigned short MOD_REMOVE = 1;
501static const unsigned short MOD_INSTALL = 2;
b9179170 502
172947cd 503bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
d8a8f9d7
MV
504{
505 std::map<unsigned short, APT::VersionSet> verset;
172947cd 506 return DoCacheManipulationFromCommandLine(CmdL, Cache, verset, UpgradeMode);
d8a8f9d7 507}
d8a8f9d7 508bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
172947cd 509 std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
b9179170 510{
b9179170
MV
511 // Enter the special broken fixing mode if the user specified arguments
512 bool BrokenFix = false;
513 if (Cache->BrokenCount() != 0)
514 BrokenFix = true;
515
be0270de 516 SPtr<pkgProblemResolver> Fix;
b9179170
MV
517 if (_config->FindB("APT::Get::CallResolver", true) == true)
518 Fix = new pkgProblemResolver(Cache);
519
b9179170
MV
520 unsigned short fallback = MOD_INSTALL;
521 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
522 fallback = MOD_REMOVE;
523 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
524 {
525 _config->Set("APT::Get::Purge", true);
526 fallback = MOD_REMOVE;
527 }
528 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
529 {
530 _config->Set("APT::Get::AutomaticRemove", "true");
531 fallback = MOD_REMOVE;
532 }
533
534 std::list<APT::VersionSet::Modifier> mods;
535 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
e6f0c9bc 536 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::CANDIDATE));
b9179170 537 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
e6f0c9bc 538 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::NEWEST));
b9179170 539 CacheSetHelperAPTGet helper(c0out);
d8a8f9d7 540 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
b9179170
MV
541 CmdL.FileList + 1, mods, fallback, helper);
542
543 if (_error->PendingError() == true)
544 {
545 helper.showVirtualPackageErrors(Cache);
b9179170
MV
546 return false;
547 }
548
549
550 TryToInstall InstallAction(Cache, Fix, BrokenFix);
551 TryToRemove RemoveAction(Cache, Fix);
552
553 // new scope for the ActionGroup
554 {
555 pkgDepCache::ActionGroup group(Cache);
556 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
557
558 for (unsigned short i = 0; order[i] != 0; ++i)
559 {
560 if (order[i] == MOD_INSTALL)
561 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
562 else if (order[i] == MOD_REMOVE)
563 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
564 }
565
566 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
567 {
568 for (unsigned short i = 0; order[i] != 0; ++i)
569 {
570 if (order[i] != MOD_INSTALL)
571 continue;
572 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
573 InstallAction.doAutoInstall();
574 }
575 }
576
577 if (_error->PendingError() == true)
578 {
b9179170
MV
579 return false;
580 }
581
582 /* If we are in the Broken fixing mode we do not attempt to fix the
583 problems. This is if the user invoked install without -f and gave
584 packages */
585 if (BrokenFix == true && Cache->BrokenCount() != 0)
586 {
587 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
588 ShowBroken(c1out,Cache,false);
b9179170
MV
589 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
590 }
591
592 if (Fix != NULL)
593 {
594 // Call the scored problem resolver
2a884c61
DK
595 OpTextProgress Progress(*_config);
596 bool const distUpgradeMode = strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0;
597
67caa2e6
DK
598 bool resolver_fail = false;
599 if (distUpgradeMode == true || UpgradeMode != APT::Upgrade::ALLOW_EVERYTHING)
2a884c61 600 resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode, &Progress);
67caa2e6
DK
601 else
602 resolver_fail = Fix->Resolve(true, &Progress);
172947cd
DK
603
604 if (resolver_fail == false && Cache->BrokenCount() == 0)
58377ceb 605 return false;
b9179170
MV
606 }
607
608 // Now we check the state of the packages,
609 if (Cache->BrokenCount() != 0)
610 {
611 c1out <<
612 _("Some packages could not be installed. This may mean that you have\n"
613 "requested an impossible situation or if you are using the unstable\n"
614 "distribution that some required packages have not yet been created\n"
615 "or been moved out of Incoming.") << std::endl;
616 /*
617 if (Packages == 1)
618 {
619 c1out << std::endl;
620 c1out <<
621 _("Since you only requested a single operation it is extremely likely that\n"
622 "the package is simply not installable and a bug report against\n"
623 "that package should be filed.") << std::endl;
624 }
625 */
626
627 c1out << _("The following information may help to resolve the situation:") << std::endl;
628 c1out << std::endl;
629 ShowBroken(c1out,Cache,false);
630 if (_error->PendingError() == true)
631 return false;
632 else
633 return _error->Error(_("Broken packages"));
634 }
635 }
636 if (!DoAutomaticRemove(Cache))
637 return false;
638
d8a8f9d7
MV
639 // if nothing changed in the cache, but only the automark information
640 // we write the StateFile here, otherwise it will be written in
641 // cache.commit()
642 if (InstallAction.AutoMarkChanged > 0 &&
643 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
644 Cache->BadCount() == 0 &&
645 _config->FindB("APT::Get::Simulate",false) == false)
646 Cache->writeStateFile(NULL);
647
648 return true;
649}
ee0167c4 650 /*}}}*/
d8a8f9d7
MV
651// DoInstall - Install packages from the command line /*{{{*/
652// ---------------------------------------------------------------------
653/* Install named packages */
654bool DoInstall(CommandLine &CmdL)
655{
656 CacheFile Cache;
0d29b9d4
MV
657 // first check for local pkgs and add them to the cache
658 for (const char **I = CmdL.FileList; *I != 0; I++)
659 {
660 if(FileExists(*I))
661 {
eafc5435
MV
662 // FIXME: make this more elegant
663 std::string TypeStr = flExtension(*I) + "-file";
664 pkgSourceList::Type *Type = pkgSourceList::Type::GetType(TypeStr.c_str());
665 if(Type != 0)
666 {
667 std::vector<metaIndex *> List;
668 std::map<std::string, std::string> Options;
669 if(Type->CreateItem(List, *I, "", "", Options))
670 {
aaf677da
MV
671 // we have our own CacheFile that gives us a SourceList
672 // with superpowerz
673 SourceList *sources = (SourceList*)Cache.GetSourceList();
94f66115 674 sources->AddMetaIndex(List[0]);
eafc5435
MV
675 }
676 }
0d29b9d4
MV
677 }
678 }
679
680 // then open the cache
d8a8f9d7
MV
681 if (Cache.OpenForInstall() == false ||
682 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
683 return false;
0d29b9d4 684
d8a8f9d7
MV
685 std::map<unsigned short, APT::VersionSet> verset;
686
172947cd 687 if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset, 0))
d8a8f9d7
MV
688 return false;
689
b9179170
MV
690 /* Print out a list of packages that are going to be installed extra
691 to what the user asked */
692 if (Cache->InstCount() != verset[MOD_INSTALL].size())
693 {
694 std::string List;
695 std::string VersionsList;
696 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
697 {
698 pkgCache::PkgIterator I(Cache,Cache.List[J]);
699 if ((*Cache)[I].Install() == false)
700 continue;
701 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
702
703 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
704 continue;
705
706 List += I.FullName(true) + " ";
707 VersionsList += std::string(Cache[I].CandVersion) + "\n";
708 }
709
710 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
711 }
712
713 /* Print out a list of suggested and recommended packages */
714 {
715 std::string SuggestsList, RecommendsList;
716 std::string SuggestsVersions, RecommendsVersions;
717 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
718 {
719 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
720
721 /* Just look at the ones we want to install */
722 if ((*Cache)[Pkg].Install() == false)
723 continue;
724
725 // get the recommends/suggests for the candidate ver
726 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
727 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
728 {
729 pkgCache::DepIterator Start;
730 pkgCache::DepIterator End;
731 D.GlobOr(Start,End); // advances D
732
733 // FIXME: we really should display a or-group as a or-group to the user
734 // the problem is that ShowList is incapable of doing this
735 std::string RecommendsOrList,RecommendsOrVersions;
736 std::string SuggestsOrList,SuggestsOrVersions;
737 bool foundInstalledInOrGroup = false;
738 for(;;)
739 {
740 /* Skip if package is installed already, or is about to be */
741 std::string target = Start.TargetPkg().FullName(true) + " ";
742 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
743 if (TarPkg->SelectedState == pkgCache::State::Install ||
744 TarPkg->SelectedState == pkgCache::State::Hold ||
745 Cache[Start.TargetPkg()].Install())
746 {
747 foundInstalledInOrGroup=true;
748 break;
749 }
750
751 /* Skip if we already saw it */
752 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
753 {
754 foundInstalledInOrGroup=true;
755 break;
756 }
757
758 // this is a dep on a virtual pkg, check if any package that provides it
759 // should be installed
760 if(Start.TargetPkg().ProvidesList() != 0)
761 {
762 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
763 for (; I.end() == false; ++I)
764 {
765 pkgCache::PkgIterator Pkg = I.OwnerPkg();
766 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
767 Pkg.CurrentVer() != 0)
768 foundInstalledInOrGroup=true;
769 }
770 }
771
772 if (Start->Type == pkgCache::Dep::Suggests)
773 {
774 SuggestsOrList += target;
775 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
776 }
777
778 if (Start->Type == pkgCache::Dep::Recommends)
779 {
780 RecommendsOrList += target;
781 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
782 }
783
784 if (Start >= End)
785 break;
786 ++Start;
787 }
788
789 if(foundInstalledInOrGroup == false)
790 {
791 RecommendsList += RecommendsOrList;
792 RecommendsVersions += RecommendsOrVersions;
793 SuggestsList += SuggestsOrList;
794 SuggestsVersions += SuggestsOrVersions;
795 }
796
797 }
798 }
799
800 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
801 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
802
803 }
804
b9179170
MV
805 // See if we need to prompt
806 // FIXME: check if really the packages in the set are going to be installed
807 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
808 return InstallPackages(Cache,false,false);
809
810 return InstallPackages(Cache,false);
811}
812 /*}}}*/
4d695011
DK
813
814// TryToInstall - Mark a package for installation /*{{{*/
815void TryToInstall::operator() (pkgCache::VerIterator const &Ver) {
816 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
817
818 Cache->GetDepCache()->SetCandidateVersion(Ver);
819 pkgDepCache::StateCache &State = (*Cache)[Pkg];
820
821 // Handle the no-upgrade case
822 if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
823 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
824 Pkg.FullName(true).c_str());
825 // Ignore request for install if package would be new
826 else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
827 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
828 Pkg.FullName(true).c_str());
829 else {
830 if (Fix != NULL) {
831 Fix->Clear(Pkg);
832 Fix->Protect(Pkg);
833 }
834 Cache->GetDepCache()->MarkInstall(Pkg,false);
835
836 if (State.Install() == false) {
837 if (_config->FindB("APT::Get::ReInstall",false) == true) {
838 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
839 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
840 Pkg.FullName(true).c_str());
841 else
842 Cache->GetDepCache()->SetReInstall(Pkg, true);
843 } else
844 ioprintf(c1out,_("%s is already the newest version.\n"),
845 Pkg.FullName(true).c_str());
846 }
847
848 // Install it with autoinstalling enabled (if we not respect the minial
849 // required deps or the policy)
850 if (FixBroken == false)
851 doAutoInstallLater.insert(Pkg);
852 }
853
854 // see if we need to fix the auto-mark flag
855 // e.g. apt-get install foo
856 // where foo is marked automatic
857 if (State.Install() == false &&
858 (State.Flags & pkgCache::Flag::Auto) &&
859 _config->FindB("APT::Get::ReInstall",false) == false &&
860 _config->FindB("APT::Get::Only-Upgrade",false) == false &&
861 _config->FindB("APT::Get::Download-Only",false) == false)
862 {
863 ioprintf(c1out,_("%s set to manually installed.\n"),
864 Pkg.FullName(true).c_str());
865 Cache->GetDepCache()->MarkAuto(Pkg,false);
866 AutoMarkChanged++;
867 }
868}
869 /*}}}*/
870bool TryToInstall::propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > const &start, std::ostream &out)/*{{{*/
871{
872 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
873 s != start.end(); ++s)
874 Cache->GetDepCache()->SetCandidateVersion(s->first);
875
876 bool Success = true;
877 // the Changed list contains:
878 // first: "new version"
879 // second: "what-caused the change"
880 std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
881 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
882 s != start.end(); ++s)
883 {
884 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
885 // We continue here even if it failed to enhance the ShowBroken output
886 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
887 }
888 for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
889 c != Changed.end(); ++c)
890 {
891 if (c->second.end() == true)
892 ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
893 c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
894 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
895 {
896 pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
897 ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
898 V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
899 }
900 }
901 return Success;
902}
903 /*}}}*/
904void TryToInstall::doAutoInstall() { /*{{{*/
905 for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
906 P != doAutoInstallLater.end(); ++P) {
907 pkgDepCache::StateCache &State = (*Cache)[P];
908 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
909 continue;
910 Cache->GetDepCache()->MarkInstall(P, true);
911 }
912 doAutoInstallLater.clear();
913}
914 /*}}}*/
915// TryToRemove - Mark a package for removal /*{{{*/
916void TryToRemove::operator() (pkgCache::VerIterator const &Ver)
917{
918 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
919
920 if (Fix != NULL)
921 {
922 Fix->Clear(Pkg);
923 Fix->Protect(Pkg);
924 Fix->Remove(Pkg);
925 }
926
927 if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
928 (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
929 {
930 pkgCache::GrpIterator Grp = Pkg.Group();
931 pkgCache::PkgIterator P = Grp.PackageList();
932 for (; P.end() != true; P = Grp.NextPkg(P))
933 {
934 if (P == Pkg)
935 continue;
936 if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
937 {
938 // TRANSLATORS: Note, this is not an interactive question
939 ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
940 Pkg.FullName(true).c_str(), P.FullName(true).c_str());
941 break;
942 }
943 }
944 if (P.end() == true)
945 ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
946
947 // MarkInstall refuses to install packages on hold
948 Pkg->SelectedState = pkgCache::State::Hold;
949 }
950 else
951 Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
952}
953 /*}}}*/