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