1 // Include Files /*{{{*/
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>
32 #include <sys/ioctl.h>
34 #include <sys/statfs.h>
35 #include <sys/statvfs.h>
44 #include "private-install.h"
45 #include "private-cachefile.h"
46 #include "private-output.h"
47 #include "private-cacheset.h"
48 #include "acqprogress.h"
53 // CheckAuth - check if each download comes form a trusted source /*{{{*/
54 // ---------------------------------------------------------------------
56 static bool CheckAuth(pkgAcquire
& Fetcher
)
58 std::string UntrustedList
;
59 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
< Fetcher
.ItemsEnd(); ++I
)
61 if (!(*I
)->IsTrusted())
63 UntrustedList
+= std::string((*I
)->ShortDesc()) + " ";
67 if (UntrustedList
== "")
72 ShowList(c2out
,_("WARNING: The following packages cannot be authenticated!"),UntrustedList
,"");
74 if (_config
->FindB("APT::Get::AllowUnauthenticated",false) == true)
76 c2out
<< _("Authentication warning overridden.\n");
80 if (_config
->FindI("quiet",0) < 2
81 && _config
->FindB("APT::Get::Assume-Yes",false) == false)
83 c2out
<< _("Install these packages without verification?") << std::flush
;
85 return _error
->Error(_("Some packages could not be authenticated"));
89 else if (_config
->FindB("APT::Get::Force-Yes",false) == true)
94 return _error
->Error(_("There are problems and -y was used without --force-yes"));
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 */
103 bool InstallPackages(CacheFile
&Cache
,bool ShwKept
,bool Ask
, bool Safety
)
105 if (_config
->FindB("APT::Get::Purge",false) == true)
107 pkgCache::PkgIterator I
= Cache
->PkgBegin();
108 for (; I
.end() == false; ++I
)
110 if (I
.Purge() == false && Cache
[I
].Mode
== pkgDepCache::ModeDelete
)
111 Cache
->MarkDelete(I
,true);
116 bool Essential
= false;
118 // Show all the various warning indicators
119 ShowDel(c1out
,Cache
);
120 ShowNew(c1out
,Cache
);
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
);
133 if (Cache
->BrokenCount() != 0)
135 ShowBroken(c1out
,Cache
,false);
136 return _error
->Error(_("Internal error, InstallPackages was called with broken packages!"));
139 if (Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
140 Cache
->BadCount() == 0)
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."));
147 // Run the simulator ..
148 if (_config
->FindB("APT::Get::Simulate") == true)
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
)
155 if (Res
!= pkgPackageManager::Completed
)
156 return _error
->Error(_("Internal error, Ordering didn't finish"));
160 // Create the text record parser
161 pkgRecords
Recs(Cache
);
162 if (_error
->PendingError() == true)
165 // Create the download object
167 AcqTextStatus
Stat(ScreenWidth
,_config
->FindI("quiet",0));
168 if (_config
->FindB("APT::Get::Print-URIs", false) == true)
170 // force a hashsum for compatibility reasons
171 _config
->CndSet("Acquire::ForceHash", "md5sum");
173 else if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::Cache::Archives")) == false)
176 // Read the source list
177 if (Cache
.BuildSourceList() == false)
179 pkgSourceList
*List
= Cache
.GetSourceList();
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)
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())
193 c0out
<< DebBytes
<< ',' << Cache
->DebSize() << std::endl
;
194 c0out
<< _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl
;
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());
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());
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());
221 if (_error
->PendingError() == true)
224 /* Check for enough free space, but only if we are actually going to
226 if (_config
->FindB("APT::Get::Print-URIs") == false &&
227 _config
->FindB("APT::Get::Download",true) == true)
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"),
236 return _error
->Errno("statvfs",_("Couldn't determine free space in %s"),
238 } else if (unsigned(Buf
.f_bfree
) < (FetchBytes
- FetchPBytes
)/Buf
.f_bsize
)
241 if (statfs(OutputDir
.c_str(),&Stat
) != 0
242 #if HAVE_STRUCT_STATFS_F_TYPE
243 || unsigned(Stat
.f_type
) != RAMFS_MAGIC
246 return _error
->Error(_("You don't have enough free space in %s."),
252 if (_config
->FindI("quiet",0) >= 2 ||
253 _config
->FindB("APT::Get::Assume-Yes",false) == true)
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"));
259 if (Essential
== true && Safety
== true)
261 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
262 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
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!");
268 _("You are about to do something potentially harmful.\n"
269 "To continue type in the phrase '%s'\n"
272 if (AnalPrompt(Prompt
) == false)
274 c2out
<< _("Abort.") << std::endl
;
280 // Prompt to continue
281 if (Ask
== true || Fail
== true)
283 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
284 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
286 if (_config
->FindI("quiet",0) < 2 &&
287 _config
->FindB("APT::Get::Assume-Yes",false) == false)
289 c2out
<< _("Do you want to continue?") << std::flush
;
290 if (YnPrompt() == false)
292 c2out
<< _("Abort.") << std::endl
;
299 // Just print out the uris an exit if the --print-uris flag was used
300 if (_config
->FindB("APT::Get::Print-URIs") == true)
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
;
309 if (!CheckAuth(Fetcher
))
312 /* Unlock the dpkg lock if we are not going to be doing an install
314 if (_config
->FindB("APT::Get::Download-Only",false) == true)
320 bool Transient
= false;
321 if (_config
->FindB("APT::Get::Download",true) == false)
323 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
< Fetcher
.ItemsEnd();)
325 if ((*I
)->Local
== true)
331 // Close the item and check if it was found in cache
333 if ((*I
)->Complete
== false)
336 // Clear it out of the fetch list
338 I
= Fetcher
.ItemsBegin();
342 if (Fetcher
.Run() == pkgAcquire::Failed
)
347 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
!= Fetcher
.ItemsEnd(); ++I
)
349 if ((*I
)->Status
== pkgAcquire::Item::StatDone
&&
350 (*I
)->Complete
== true)
353 if ((*I
)->Status
== pkgAcquire::Item::StatIdle
)
360 fprintf(stderr
,_("Failed to fetch %s %s\n"),(*I
)->DescURI().c_str(),
361 (*I
)->ErrorText
.c_str());
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)
375 if (_config
->FindB("APT::Get::Download-Only",false) == true)
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
;
383 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
385 return _error
->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
388 if (Transient
== true && Failed
== true)
389 return _error
->Error(_("--fix-missing and media swapping is not currently supported"));
391 // Try to deal with missing package files
392 if (Failed
== true && PM
->FixMissing() == false)
394 c2out
<< _("Unable to correct missing packages.") << std::endl
;
395 return _error
->Error(_("Aborting install."));
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)
403 if (Res
== pkgPackageManager::Completed
)
406 // Reload the fetcher object and loop again for media swapping
408 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false)
414 std::set
<std::string
> const disappearedPkgs
= PM
->GetDisappearedPackages();
415 if (disappearedPkgs
.empty() == true)
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(" ");
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
;
434 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
435 // ---------------------------------------------------------------------
436 /* Remove unused automatic packages */
437 bool DoAutomaticRemove(CacheFile
&Cache
)
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");
443 pkgDepCache::ActionGroup
group(*Cache
);
445 std::cout
<< "DoAutomaticRemove()" << std::endl
;
447 if (doAutoRemove
== true &&
448 _config
->FindB("APT::Get::Remove",true) == false)
450 c1out
<< _("We are not supposed to delete stuff, can't start "
451 "AutoRemover") << std::endl
;
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);
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
)
465 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
466 if (Cache
[Pkg
].Garbage
)
468 if(Pkg
.CurrentVer() != 0 || Cache
[Pkg
].Install())
470 std::cout
<< "We could delete %s" << Pkg
.FullName(true).c_str() << std::endl
;
474 if(Pkg
.CurrentVer() != 0 &&
475 Pkg
->CurrentState
!= pkgCache::State::ConfigFiles
)
476 Cache
->MarkDelete(Pkg
, purgePkgs
, 0, false);
478 Cache
->MarkKeep(Pkg
, false, false);
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)
488 if (Pkg
.CandVersion() != 0)
490 Cache
->MarkDelete(Pkg
, false, 0, false);
492 // only show stuff in the list that is not yet marked for removal
493 else if(hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
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))
506 for (APT::PackageSet::const_iterator Pkg
= tooMuch
.begin();
507 Pkg
!= tooMuch
.end() && Changed
== false; ++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
)
519 if (R
.IsNegative() == true ||
520 Cache
->IsImportantDep(R
) == false)
522 pkgCache::PkgIterator N
= R
.ParentPkg();
523 if (N
.end() == true || (N
->CurrentVer
== 0 && (*Cache
)[N
].Install() == false))
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)
536 } while (Changed
== true);
539 std::string autoremovelist
, autoremoveversions
;
540 if (smallList
== false && autoRemoveCount
!= 0)
542 for (APT::PackageList::const_iterator Pkg
= autoRemoveList
.begin(); Pkg
!= autoRemoveList
.end(); ++Pkg
)
544 if (Cache
[Pkg
].Garbage
== false)
546 autoremovelist
+= Pkg
.FullName(true) + " ";
547 autoremoveversions
+= std::string(Cache
[Pkg
].CandVersion
) + "\n";
551 // Now see if we had destroyed anything (if we had done anything)
552 if (Cache
->BrokenCount() != 0)
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
;
557 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
559 ShowBroken(c1out
,Cache
,false);
561 return _error
->Error(_("Internal Error, AutoRemover broke stuff"));
564 // if we don't remove them, we should show them!
565 if (doAutoRemove
== false && (autoremovelist
.empty() == false || autoRemoveCount
!= 0))
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
);
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
;
583 // DoInstall - Install packages from the command line /*{{{*/
584 // ---------------------------------------------------------------------
585 /* Install named packages */
586 bool DoInstall(CommandLine
&CmdL
)
589 if (Cache
.OpenForInstall() == false ||
590 Cache
.CheckDeps(CmdL
.FileSize() != 1) == false)
593 // Enter the special broken fixing mode if the user specified arguments
594 bool BrokenFix
= false;
595 if (Cache
->BrokenCount() != 0)
598 pkgProblemResolver
* Fix
= NULL
;
599 if (_config
->FindB("APT::Get::CallResolver", true) == true)
600 Fix
= new pkgProblemResolver(Cache
);
602 static const unsigned short MOD_REMOVE
= 1;
603 static const unsigned short MOD_INSTALL
= 2;
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)
610 _config
->Set("APT::Get::Purge", true);
611 fallback
= MOD_REMOVE
;
613 else if (strcasecmp(CmdL
.FileList
[0], "autoremove") == 0)
615 _config
->Set("APT::Get::AutomaticRemove", "true");
616 fallback
= MOD_REMOVE
;
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
);
628 if (_error
->PendingError() == true)
630 helper
.showVirtualPackageErrors(Cache
);
637 TryToInstall
InstallAction(Cache
, Fix
, BrokenFix
);
638 TryToRemove
RemoveAction(Cache
, Fix
);
640 // new scope for the ActionGroup
642 pkgDepCache::ActionGroup
group(Cache
);
643 unsigned short const order
[] = { MOD_REMOVE
, MOD_INSTALL
, 0 };
645 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
647 if (order
[i
] == MOD_INSTALL
)
648 InstallAction
= std::for_each(verset
[MOD_INSTALL
].begin(), verset
[MOD_INSTALL
].end(), InstallAction
);
649 else if (order
[i
] == MOD_REMOVE
)
650 RemoveAction
= std::for_each(verset
[MOD_REMOVE
].begin(), verset
[MOD_REMOVE
].end(), RemoveAction
);
653 if (Fix
!= NULL
&& _config
->FindB("APT::Get::AutoSolving", true) == true)
655 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
657 if (order
[i
] != MOD_INSTALL
)
659 InstallAction
.propergateReleaseCandiateSwitching(helper
.selectedByRelease
, c0out
);
660 InstallAction
.doAutoInstall();
664 if (_error
->PendingError() == true)
671 /* If we are in the Broken fixing mode we do not attempt to fix the
672 problems. This is if the user invoked install without -f and gave
674 if (BrokenFix
== true && Cache
->BrokenCount() != 0)
676 c1out
<< _("You might want to run 'apt-get -f install' to correct these:") << std::endl
;
677 ShowBroken(c1out
,Cache
,false);
680 return _error
->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
685 // Call the scored problem resolver
690 // Now we check the state of the packages,
691 if (Cache
->BrokenCount() != 0)
694 _("Some packages could not be installed. This may mean that you have\n"
695 "requested an impossible situation or if you are using the unstable\n"
696 "distribution that some required packages have not yet been created\n"
697 "or been moved out of Incoming.") << std::endl
;
703 _("Since you only requested a single operation it is extremely likely that\n"
704 "the package is simply not installable and a bug report against\n"
705 "that package should be filed.") << std::endl;
709 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
711 ShowBroken(c1out
,Cache
,false);
712 if (_error
->PendingError() == true)
715 return _error
->Error(_("Broken packages"));
718 if (!DoAutomaticRemove(Cache
))
721 /* Print out a list of packages that are going to be installed extra
722 to what the user asked */
723 if (Cache
->InstCount() != verset
[MOD_INSTALL
].size())
726 std::string VersionsList
;
727 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
729 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
730 if ((*Cache
)[I
].Install() == false)
732 pkgCache::VerIterator Cand
= Cache
[I
].CandidateVerIter(Cache
);
734 if (verset
[MOD_INSTALL
].find(Cand
) != verset
[MOD_INSTALL
].end())
737 List
+= I
.FullName(true) + " ";
738 VersionsList
+= std::string(Cache
[I
].CandVersion
) + "\n";
741 ShowList(c1out
,_("The following extra packages will be installed:"),List
,VersionsList
);
744 /* Print out a list of suggested and recommended packages */
746 std::string SuggestsList
, RecommendsList
;
747 std::string SuggestsVersions
, RecommendsVersions
;
748 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
750 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
752 /* Just look at the ones we want to install */
753 if ((*Cache
)[Pkg
].Install() == false)
756 // get the recommends/suggests for the candidate ver
757 pkgCache::VerIterator CV
= (*Cache
)[Pkg
].CandidateVerIter(*Cache
);
758 for (pkgCache::DepIterator D
= CV
.DependsList(); D
.end() == false; )
760 pkgCache::DepIterator Start
;
761 pkgCache::DepIterator End
;
762 D
.GlobOr(Start
,End
); // advances D
764 // FIXME: we really should display a or-group as a or-group to the user
765 // the problem is that ShowList is incapable of doing this
766 std::string RecommendsOrList
,RecommendsOrVersions
;
767 std::string SuggestsOrList
,SuggestsOrVersions
;
768 bool foundInstalledInOrGroup
= false;
771 /* Skip if package is installed already, or is about to be */
772 std::string target
= Start
.TargetPkg().FullName(true) + " ";
773 pkgCache::PkgIterator
const TarPkg
= Start
.TargetPkg();
774 if (TarPkg
->SelectedState
== pkgCache::State::Install
||
775 TarPkg
->SelectedState
== pkgCache::State::Hold
||
776 Cache
[Start
.TargetPkg()].Install())
778 foundInstalledInOrGroup
=true;
782 /* Skip if we already saw it */
783 if (int(SuggestsList
.find(target
)) != -1 || int(RecommendsList
.find(target
)) != -1)
785 foundInstalledInOrGroup
=true;
789 // this is a dep on a virtual pkg, check if any package that provides it
790 // should be installed
791 if(Start
.TargetPkg().ProvidesList() != 0)
793 pkgCache::PrvIterator I
= Start
.TargetPkg().ProvidesList();
794 for (; I
.end() == false; ++I
)
796 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
797 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer() &&
798 Pkg
.CurrentVer() != 0)
799 foundInstalledInOrGroup
=true;
803 if (Start
->Type
== pkgCache::Dep::Suggests
)
805 SuggestsOrList
+= target
;
806 SuggestsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
809 if (Start
->Type
== pkgCache::Dep::Recommends
)
811 RecommendsOrList
+= target
;
812 RecommendsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
820 if(foundInstalledInOrGroup
== false)
822 RecommendsList
+= RecommendsOrList
;
823 RecommendsVersions
+= RecommendsOrVersions
;
824 SuggestsList
+= SuggestsOrList
;
825 SuggestsVersions
+= SuggestsOrVersions
;
831 ShowList(c1out
,_("Suggested packages:"),SuggestsList
,SuggestsVersions
);
832 ShowList(c1out
,_("Recommended packages:"),RecommendsList
,RecommendsVersions
);
836 // if nothing changed in the cache, but only the automark information
837 // we write the StateFile here, otherwise it will be written in
839 if (InstallAction
.AutoMarkChanged
> 0 &&
840 Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
841 Cache
->BadCount() == 0 &&
842 _config
->FindB("APT::Get::Simulate",false) == false)
843 Cache
->writeStateFile(NULL
);
845 // See if we need to prompt
846 // FIXME: check if really the packages in the set are going to be installed
847 if (Cache
->InstCount() == verset
[MOD_INSTALL
].size() && Cache
->DelCount() == 0)
848 return InstallPackages(Cache
,false,false);
850 return InstallPackages(Cache
,false);