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>
27 #include <apt-private/private-progress.h>
34 #include <sys/ioctl.h>
36 #include <sys/statfs.h>
37 #include <sys/statvfs.h>
46 #include "private-install.h"
47 #include "private-download.h"
48 #include "private-cachefile.h"
49 #include "private-output.h"
50 #include "private-cacheset.h"
51 #include "acqprogress.h"
56 // InstallPackages - Actually download and install the packages /*{{{*/
57 // ---------------------------------------------------------------------
58 /* This displays the informative messages describing what is going to
59 happen and then calls the download routines */
60 bool InstallPackages(CacheFile
&Cache
,bool ShwKept
,bool Ask
, bool Safety
)
62 if (_config
->FindB("APT::Get::Purge",false) == true)
64 pkgCache::PkgIterator I
= Cache
->PkgBegin();
65 for (; I
.end() == false; ++I
)
67 if (I
.Purge() == false && Cache
[I
].Mode
== pkgDepCache::ModeDelete
)
68 Cache
->MarkDelete(I
,true);
73 bool Essential
= false;
75 // Show all the various warning indicators
79 ShowKept(c1out
,Cache
);
80 Fail
|= !ShowHold(c1out
,Cache
);
81 if (_config
->FindB("APT::Get::Show-Upgraded",true) == true)
82 ShowUpgraded(c1out
,Cache
);
83 Fail
|= !ShowDowngraded(c1out
,Cache
);
84 if (_config
->FindB("APT::Get::Download-Only",false) == false)
85 Essential
= !ShowEssential(c1out
,Cache
);
90 if (Cache
->BrokenCount() != 0)
92 ShowBroken(c1out
,Cache
,false);
93 return _error
->Error(_("Internal error, InstallPackages was called with broken packages!"));
96 if (Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
97 Cache
->BadCount() == 0)
101 if (Cache
->DelCount() != 0 && _config
->FindB("APT::Get::Remove",true) == false)
102 return _error
->Error(_("Packages need to be removed but remove is disabled."));
104 // Run the simulator ..
105 if (_config
->FindB("APT::Get::Simulate") == true)
107 pkgSimulate
PM(Cache
);
109 int status_fd
= _config
->FindI("APT::Status-Fd",-1);
110 APT::Progress::PackageManager
*progress
= NULL
;
112 progress
= new APT::Progress::PackageManagerProgressFd(status_fd
);
113 pkgPackageManager::OrderResult Res
= PM
.DoInstall(progress
);
116 if (Res
== pkgPackageManager::Failed
)
118 if (Res
!= pkgPackageManager::Completed
)
119 return _error
->Error(_("Internal error, Ordering didn't finish"));
123 // Create the text record parser
124 pkgRecords
Recs(Cache
);
125 if (_error
->PendingError() == true)
128 // Create the download object
130 AcqTextStatus
Stat(ScreenWidth
,_config
->FindI("quiet",0));
131 if (_config
->FindB("APT::Get::Print-URIs", false) == true)
133 // force a hashsum for compatibility reasons
134 _config
->CndSet("Acquire::ForceHash", "md5sum");
136 else if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::Cache::Archives")) == false)
139 // Read the source list
140 if (Cache
.BuildSourceList() == false)
142 pkgSourceList
*List
= Cache
.GetSourceList();
144 // Create the package manager and prepare to download
145 SPtr
<pkgPackageManager
> PM
= _system
->CreatePM(Cache
);
146 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false ||
147 _error
->PendingError() == true)
150 // Display statistics
151 unsigned long long FetchBytes
= Fetcher
.FetchNeeded();
152 unsigned long long FetchPBytes
= Fetcher
.PartialPresent();
153 unsigned long long DebBytes
= Fetcher
.TotalNeeded();
154 if (DebBytes
!= Cache
->DebSize())
156 c0out
<< DebBytes
<< ',' << Cache
->DebSize() << std::endl
;
157 c0out
<< _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl
;
161 if (DebBytes
!= FetchBytes
)
162 //TRANSLATOR: The required space between number and unit is already included
163 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
164 ioprintf(c1out
,_("Need to get %sB/%sB of archives.\n"),
165 SizeToStr(FetchBytes
).c_str(),SizeToStr(DebBytes
).c_str());
166 else if (DebBytes
!= 0)
167 //TRANSLATOR: The required space between number and unit is already included
168 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
169 ioprintf(c1out
,_("Need to get %sB of archives.\n"),
170 SizeToStr(DebBytes
).c_str());
173 if (Cache
->UsrSize() >= 0)
174 //TRANSLATOR: The required space between number and unit is already included
175 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
176 ioprintf(c1out
,_("After this operation, %sB of additional disk space will be used.\n"),
177 SizeToStr(Cache
->UsrSize()).c_str());
179 //TRANSLATOR: The required space between number and unit is already included
180 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
181 ioprintf(c1out
,_("After this operation, %sB disk space will be freed.\n"),
182 SizeToStr(-1*Cache
->UsrSize()).c_str());
184 if (_error
->PendingError() == true)
187 /* Check for enough free space, but only if we are actually going to
189 if (_config
->FindB("APT::Get::Print-URIs") == false &&
190 _config
->FindB("APT::Get::Download",true) == true)
193 std::string OutputDir
= _config
->FindDir("Dir::Cache::Archives");
194 if (statvfs(OutputDir
.c_str(),&Buf
) != 0) {
195 if (errno
== EOVERFLOW
)
196 return _error
->WarningE("statvfs",_("Couldn't determine free space in %s"),
199 return _error
->Errno("statvfs",_("Couldn't determine free space in %s"),
201 } else if (unsigned(Buf
.f_bfree
) < (FetchBytes
- FetchPBytes
)/Buf
.f_bsize
)
204 if (statfs(OutputDir
.c_str(),&Stat
) != 0
205 #if HAVE_STRUCT_STATFS_F_TYPE
206 || unsigned(Stat
.f_type
) != RAMFS_MAGIC
209 return _error
->Error(_("You don't have enough free space in %s."),
215 if (_config
->FindI("quiet",0) >= 2 ||
216 _config
->FindB("APT::Get::Assume-Yes",false) == true)
218 if (Fail
== true && _config
->FindB("APT::Get::Force-Yes",false) == false)
219 return _error
->Error(_("There are problems and -y was used without --force-yes"));
222 if (Essential
== true && Safety
== true)
224 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
225 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
227 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
228 // careful with hard to type or special characters (like non-breaking spaces)
229 const char *Prompt
= _("Yes, do as I say!");
231 _("You are about to do something potentially harmful.\n"
232 "To continue type in the phrase '%s'\n"
235 if (AnalPrompt(Prompt
) == false)
237 c2out
<< _("Abort.") << std::endl
;
243 // Prompt to continue
244 if (Ask
== true || Fail
== true)
246 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
247 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
249 if (_config
->FindI("quiet",0) < 2 &&
250 _config
->FindB("APT::Get::Assume-Yes",false) == false)
252 c2out
<< _("Do you want to continue?") << std::flush
;
253 if (YnPrompt() == false)
255 c2out
<< _("Abort.") << std::endl
;
262 // Just print out the uris an exit if the --print-uris flag was used
263 if (_config
->FindB("APT::Get::Print-URIs") == true)
265 pkgAcquire::UriIterator I
= Fetcher
.UriBegin();
266 for (; I
!= Fetcher
.UriEnd(); ++I
)
267 std::cout
<< '\'' << I
->URI
<< "' " << flNotDir(I
->Owner
->DestFile
) << ' ' <<
268 I
->Owner
->FileSize
<< ' ' << I
->Owner
->HashSum() << std::endl
;
272 if (!CheckAuth(Fetcher
, true))
275 /* Unlock the dpkg lock if we are not going to be doing an install
277 if (_config
->FindB("APT::Get::Download-Only",false) == true)
283 bool Transient
= false;
284 if (_config
->FindB("APT::Get::Download",true) == false)
286 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
< Fetcher
.ItemsEnd();)
288 if ((*I
)->Local
== true)
294 // Close the item and check if it was found in cache
296 if ((*I
)->Complete
== false)
299 // Clear it out of the fetch list
301 I
= Fetcher
.ItemsBegin();
306 if (AcquireRun(Fetcher
, 0, &Failed
, &Transient
) == false)
309 /* If we are in no download mode and missing files and there were
310 'failures' then the user must specify -m. Furthermore, there
311 is no such thing as a transient error in no-download mode! */
312 if (Transient
== true &&
313 _config
->FindB("APT::Get::Download",true) == false)
319 if (_config
->FindB("APT::Get::Download-Only",false) == true)
321 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
322 return _error
->Error(_("Some files failed to download"));
323 c1out
<< _("Download complete and in download only mode") << std::endl
;
327 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
329 return _error
->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
332 if (Transient
== true && Failed
== true)
333 return _error
->Error(_("--fix-missing and media swapping is not currently supported"));
335 // Try to deal with missing package files
336 if (Failed
== true && PM
->FixMissing() == false)
338 c2out
<< _("Unable to correct missing packages.") << std::endl
;
339 return _error
->Error(_("Aborting install."));
344 // FIXME: make this a factory
345 // select the right progress
346 int status_fd
= _config
->FindI("APT::Status-Fd", -1);
347 int status_deb822_fd
= _config
->FindI("APT::Status-deb822-Fd", -1);
349 APT::Progress::PackageManager
*progress
= NULL
;
350 if (status_deb822_fd
> 0)
351 progress
= new APT::Progress::PackageManagerProgressDeb822Fd(
353 else if (status_fd
> 0)
354 progress
= new APT::Progress::PackageManagerProgressFd(status_fd
);
355 else if(_config
->FindB("Dpkg::Progress-Fancy", false) == true)
356 progress
= new APT::Progress::PackageManagerFancy();
357 else if (_config
->FindB("Dpkg::Progress",
358 _config
->FindB("DpkgPM::Progress", false)) == true)
359 progress
= new APT::Progress::PackageManagerText();
361 progress
= new APT::Progress::PackageManager();
362 pkgPackageManager::OrderResult Res
= PM
->DoInstall(progress
);
365 if (Res
== pkgPackageManager::Failed
|| _error
->PendingError() == true)
367 if (Res
== pkgPackageManager::Completed
)
370 // Reload the fetcher object and loop again for media swapping
372 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false)
378 std::set
<std::string
> const disappearedPkgs
= PM
->GetDisappearedPackages();
379 if (disappearedPkgs
.empty() == true)
382 std::string disappear
;
383 for (std::set
<std::string
>::const_iterator d
= disappearedPkgs
.begin();
384 d
!= disappearedPkgs
.end(); ++d
)
385 disappear
.append(*d
).append(" ");
387 ShowList(c1out
, P_("The following package disappeared from your system as\n"
388 "all files have been overwritten by other packages:",
389 "The following packages disappeared from your system as\n"
390 "all files have been overwritten by other packages:", disappearedPkgs
.size()), disappear
, "");
391 c0out
<< _("Note: This is done automatically and on purpose by dpkg.") << std::endl
;
396 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
397 // ---------------------------------------------------------------------
398 /* Remove unused automatic packages */
399 bool DoAutomaticRemove(CacheFile
&Cache
)
401 bool Debug
= _config
->FindI("Debug::pkgAutoRemove",false);
402 bool doAutoRemove
= _config
->FindB("APT::Get::AutomaticRemove", false);
403 bool hideAutoRemove
= _config
->FindB("APT::Get::HideAutoRemove");
405 pkgDepCache::ActionGroup
group(*Cache
);
407 std::cout
<< "DoAutomaticRemove()" << std::endl
;
409 if (doAutoRemove
== true &&
410 _config
->FindB("APT::Get::Remove",true) == false)
412 c1out
<< _("We are not supposed to delete stuff, can't start "
413 "AutoRemover") << std::endl
;
417 bool purgePkgs
= _config
->FindB("APT::Get::Purge", false);
418 bool smallList
= (hideAutoRemove
== false &&
419 strcasecmp(_config
->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
421 unsigned long autoRemoveCount
= 0;
422 APT::PackageSet tooMuch
;
423 APT::PackageList autoRemoveList
;
424 // look over the cache to see what can be removed
425 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; ++J
)
427 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
428 if (Cache
[Pkg
].Garbage
)
430 if(Pkg
.CurrentVer() != 0 || Cache
[Pkg
].Install())
432 std::cout
<< "We could delete %s" << Pkg
.FullName(true).c_str() << std::endl
;
436 if(Pkg
.CurrentVer() != 0 &&
437 Pkg
->CurrentState
!= pkgCache::State::ConfigFiles
)
438 Cache
->MarkDelete(Pkg
, purgePkgs
, 0, false);
440 Cache
->MarkKeep(Pkg
, false, false);
444 if (hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
445 autoRemoveList
.insert(Pkg
);
446 // if the package is a new install and already garbage we don't need to
447 // install it in the first place, so nuke it instead of show it
448 if (Cache
[Pkg
].Install() == true && Pkg
.CurrentVer() == 0)
450 if (Pkg
.CandVersion() != 0)
452 Cache
->MarkDelete(Pkg
, false, 0, false);
454 // only show stuff in the list that is not yet marked for removal
455 else if(hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
461 // we could have removed a new dependency of a garbage package,
462 // so check if a reverse depends is broken and if so install it again.
463 if (tooMuch
.empty() == false && (Cache
->BrokenCount() != 0 || Cache
->PolicyBrokenCount() != 0))
468 for (APT::PackageSet::const_iterator Pkg
= tooMuch
.begin();
469 Pkg
!= tooMuch
.end(); ++Pkg
)
473 for (pkgCache::PrvIterator Prv
= Cache
[Pkg
].CandidateVerIter(Cache
).ProvidesList();
474 Prv
.end() == false; ++Prv
)
475 too
.insert(Prv
.ParentPkg());
476 for (APT::PackageSet::const_iterator P
= too
.begin(); P
!= too
.end(); ++P
)
478 for (pkgCache::DepIterator R
= P
.RevDependsList();
479 R
.end() == false; ++R
)
481 if (R
.IsNegative() == true ||
482 Cache
->IsImportantDep(R
) == false)
484 pkgCache::PkgIterator N
= R
.ParentPkg();
485 if (N
.end() == true || (N
->CurrentVer
== 0 && (*Cache
)[N
].Install() == false))
488 std::clog
<< "Save " << Pkg
<< " as another installed garbage package depends on it" << std::endl
;
489 Cache
->MarkInstall(Pkg
, false, 0, false);
490 if (hideAutoRemove
== false)
502 } while (Changed
== true);
505 std::string autoremovelist
, autoremoveversions
;
506 if (smallList
== false && autoRemoveCount
!= 0)
508 for (APT::PackageList::const_iterator Pkg
= autoRemoveList
.begin(); Pkg
!= autoRemoveList
.end(); ++Pkg
)
510 if (Cache
[Pkg
].Garbage
== false)
512 autoremovelist
+= Pkg
.FullName(true) + " ";
513 autoremoveversions
+= std::string(Cache
[Pkg
].CandVersion
) + "\n";
517 // Now see if we had destroyed anything (if we had done anything)
518 if (Cache
->BrokenCount() != 0)
520 c1out
<< _("Hmm, seems like the AutoRemover destroyed something which really\n"
521 "shouldn't happen. Please file a bug report against apt.") << std::endl
;
523 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
525 ShowBroken(c1out
,Cache
,false);
527 return _error
->Error(_("Internal Error, AutoRemover broke stuff"));
530 // if we don't remove them, we should show them!
531 if (doAutoRemove
== false && (autoremovelist
.empty() == false || autoRemoveCount
!= 0))
533 if (smallList
== false)
534 ShowList(c1out
, P_("The following package was automatically installed and is no longer required:",
535 "The following packages were automatically installed and are no longer required:",
536 autoRemoveCount
), autoremovelist
, autoremoveversions
);
538 ioprintf(c1out
, P_("%lu package was automatically installed and is no longer required.\n",
539 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount
), autoRemoveCount
);
540 c1out
<< P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount
) << std::endl
;
545 // DoCacheManipulationFromCommandLine /*{{{*/
546 static const unsigned short MOD_REMOVE
= 1;
547 static const unsigned short MOD_INSTALL
= 2;
549 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
)
551 std::map
<unsigned short, APT::VersionSet
> verset
;
552 return DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
);
554 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
,
555 std::map
<unsigned short, APT::VersionSet
> &verset
)
558 // Enter the special broken fixing mode if the user specified arguments
559 bool BrokenFix
= false;
560 if (Cache
->BrokenCount() != 0)
563 SPtr
<pkgProblemResolver
> Fix
;
564 if (_config
->FindB("APT::Get::CallResolver", true) == true)
565 Fix
= new pkgProblemResolver(Cache
);
567 unsigned short fallback
= MOD_INSTALL
;
568 if (strcasecmp(CmdL
.FileList
[0],"remove") == 0)
569 fallback
= MOD_REMOVE
;
570 else if (strcasecmp(CmdL
.FileList
[0], "purge") == 0)
572 _config
->Set("APT::Get::Purge", true);
573 fallback
= MOD_REMOVE
;
575 else if (strcasecmp(CmdL
.FileList
[0], "autoremove") == 0)
577 _config
->Set("APT::Get::AutomaticRemove", "true");
578 fallback
= MOD_REMOVE
;
581 std::list
<APT::VersionSet::Modifier
> mods
;
582 mods
.push_back(APT::VersionSet::Modifier(MOD_INSTALL
, "+",
583 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::CANDIDATE
));
584 mods
.push_back(APT::VersionSet::Modifier(MOD_REMOVE
, "-",
585 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::NEWEST
));
586 CacheSetHelperAPTGet
helper(c0out
);
587 verset
= APT::VersionSet::GroupedFromCommandLine(Cache
,
588 CmdL
.FileList
+ 1, mods
, fallback
, helper
);
590 if (_error
->PendingError() == true)
592 helper
.showVirtualPackageErrors(Cache
);
597 TryToInstall
InstallAction(Cache
, Fix
, BrokenFix
);
598 TryToRemove
RemoveAction(Cache
, Fix
);
600 // new scope for the ActionGroup
602 pkgDepCache::ActionGroup
group(Cache
);
603 unsigned short const order
[] = { MOD_REMOVE
, MOD_INSTALL
, 0 };
605 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
607 if (order
[i
] == MOD_INSTALL
)
608 InstallAction
= std::for_each(verset
[MOD_INSTALL
].begin(), verset
[MOD_INSTALL
].end(), InstallAction
);
609 else if (order
[i
] == MOD_REMOVE
)
610 RemoveAction
= std::for_each(verset
[MOD_REMOVE
].begin(), verset
[MOD_REMOVE
].end(), RemoveAction
);
613 if (Fix
!= NULL
&& _config
->FindB("APT::Get::AutoSolving", true) == true)
615 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
617 if (order
[i
] != MOD_INSTALL
)
619 InstallAction
.propergateReleaseCandiateSwitching(helper
.selectedByRelease
, c0out
);
620 InstallAction
.doAutoInstall();
624 if (_error
->PendingError() == true)
629 /* If we are in the Broken fixing mode we do not attempt to fix the
630 problems. This is if the user invoked install without -f and gave
632 if (BrokenFix
== true && Cache
->BrokenCount() != 0)
634 c1out
<< _("You might want to run 'apt-get -f install' to correct these:") << std::endl
;
635 ShowBroken(c1out
,Cache
,false);
636 return _error
->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
641 // Call the scored problem resolver
645 // Now we check the state of the packages,
646 if (Cache
->BrokenCount() != 0)
649 _("Some packages could not be installed. This may mean that you have\n"
650 "requested an impossible situation or if you are using the unstable\n"
651 "distribution that some required packages have not yet been created\n"
652 "or been moved out of Incoming.") << std::endl
;
658 _("Since you only requested a single operation it is extremely likely that\n"
659 "the package is simply not installable and a bug report against\n"
660 "that package should be filed.") << std::endl;
664 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
666 ShowBroken(c1out
,Cache
,false);
667 if (_error
->PendingError() == true)
670 return _error
->Error(_("Broken packages"));
673 if (!DoAutomaticRemove(Cache
))
676 // if nothing changed in the cache, but only the automark information
677 // we write the StateFile here, otherwise it will be written in
679 if (InstallAction
.AutoMarkChanged
> 0 &&
680 Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
681 Cache
->BadCount() == 0 &&
682 _config
->FindB("APT::Get::Simulate",false) == false)
683 Cache
->writeStateFile(NULL
);
688 // DoInstall - Install packages from the command line /*{{{*/
689 // ---------------------------------------------------------------------
690 /* Install named packages */
691 bool DoInstall(CommandLine
&CmdL
)
694 if (Cache
.OpenForInstall() == false ||
695 Cache
.CheckDeps(CmdL
.FileSize() != 1) == false)
698 std::map
<unsigned short, APT::VersionSet
> verset
;
700 if(!DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
))
703 /* Print out a list of packages that are going to be installed extra
704 to what the user asked */
705 if (Cache
->InstCount() != verset
[MOD_INSTALL
].size())
708 std::string VersionsList
;
709 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
711 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
712 if ((*Cache
)[I
].Install() == false)
714 pkgCache::VerIterator Cand
= Cache
[I
].CandidateVerIter(Cache
);
716 if (verset
[MOD_INSTALL
].find(Cand
) != verset
[MOD_INSTALL
].end())
719 List
+= I
.FullName(true) + " ";
720 VersionsList
+= std::string(Cache
[I
].CandVersion
) + "\n";
723 ShowList(c1out
,_("The following extra packages will be installed:"),List
,VersionsList
);
726 /* Print out a list of suggested and recommended packages */
728 std::string SuggestsList
, RecommendsList
;
729 std::string SuggestsVersions
, RecommendsVersions
;
730 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
732 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
734 /* Just look at the ones we want to install */
735 if ((*Cache
)[Pkg
].Install() == false)
738 // get the recommends/suggests for the candidate ver
739 pkgCache::VerIterator CV
= (*Cache
)[Pkg
].CandidateVerIter(*Cache
);
740 for (pkgCache::DepIterator D
= CV
.DependsList(); D
.end() == false; )
742 pkgCache::DepIterator Start
;
743 pkgCache::DepIterator End
;
744 D
.GlobOr(Start
,End
); // advances D
746 // FIXME: we really should display a or-group as a or-group to the user
747 // the problem is that ShowList is incapable of doing this
748 std::string RecommendsOrList
,RecommendsOrVersions
;
749 std::string SuggestsOrList
,SuggestsOrVersions
;
750 bool foundInstalledInOrGroup
= false;
753 /* Skip if package is installed already, or is about to be */
754 std::string target
= Start
.TargetPkg().FullName(true) + " ";
755 pkgCache::PkgIterator
const TarPkg
= Start
.TargetPkg();
756 if (TarPkg
->SelectedState
== pkgCache::State::Install
||
757 TarPkg
->SelectedState
== pkgCache::State::Hold
||
758 Cache
[Start
.TargetPkg()].Install())
760 foundInstalledInOrGroup
=true;
764 /* Skip if we already saw it */
765 if (int(SuggestsList
.find(target
)) != -1 || int(RecommendsList
.find(target
)) != -1)
767 foundInstalledInOrGroup
=true;
771 // this is a dep on a virtual pkg, check if any package that provides it
772 // should be installed
773 if(Start
.TargetPkg().ProvidesList() != 0)
775 pkgCache::PrvIterator I
= Start
.TargetPkg().ProvidesList();
776 for (; I
.end() == false; ++I
)
778 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
779 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer() &&
780 Pkg
.CurrentVer() != 0)
781 foundInstalledInOrGroup
=true;
785 if (Start
->Type
== pkgCache::Dep::Suggests
)
787 SuggestsOrList
+= target
;
788 SuggestsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
791 if (Start
->Type
== pkgCache::Dep::Recommends
)
793 RecommendsOrList
+= target
;
794 RecommendsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
802 if(foundInstalledInOrGroup
== false)
804 RecommendsList
+= RecommendsOrList
;
805 RecommendsVersions
+= RecommendsOrVersions
;
806 SuggestsList
+= SuggestsOrList
;
807 SuggestsVersions
+= SuggestsOrVersions
;
813 ShowList(c1out
,_("Suggested packages:"),SuggestsList
,SuggestsVersions
);
814 ShowList(c1out
,_("Recommended packages:"),RecommendsList
,RecommendsVersions
);
818 // See if we need to prompt
819 // FIXME: check if really the packages in the set are going to be installed
820 if (Cache
->InstCount() == verset
[MOD_INSTALL
].size() && Cache
->DelCount() == 0)
821 return InstallPackages(Cache
,false,false);
823 return InstallPackages(Cache
,false);