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-download.h"
46 #include "private-cachefile.h"
47 #include "private-output.h"
48 #include "private-cacheset.h"
49 #include "acqprogress.h"
54 // InstallPackages - Actually download and install the packages /*{{{*/
55 // ---------------------------------------------------------------------
56 /* This displays the informative messages describing what is going to
57 happen and then calls the download routines */
58 bool InstallPackages(CacheFile
&Cache
,bool ShwKept
,bool Ask
, bool Safety
)
60 if (_config
->FindB("APT::Get::Purge",false) == true)
62 pkgCache::PkgIterator I
= Cache
->PkgBegin();
63 for (; I
.end() == false; ++I
)
65 if (I
.Purge() == false && Cache
[I
].Mode
== pkgDepCache::ModeDelete
)
66 Cache
->MarkDelete(I
,true);
71 bool Essential
= false;
73 // Show all the various warning indicators
77 ShowKept(c1out
,Cache
);
78 Fail
|= !ShowHold(c1out
,Cache
);
79 if (_config
->FindB("APT::Get::Show-Upgraded",true) == true)
80 ShowUpgraded(c1out
,Cache
);
81 Fail
|= !ShowDowngraded(c1out
,Cache
);
82 if (_config
->FindB("APT::Get::Download-Only",false) == false)
83 Essential
= !ShowEssential(c1out
,Cache
);
88 if (Cache
->BrokenCount() != 0)
90 ShowBroken(c1out
,Cache
,false);
91 return _error
->Error(_("Internal error, InstallPackages was called with broken packages!"));
94 if (Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
95 Cache
->BadCount() == 0)
99 if (Cache
->DelCount() != 0 && _config
->FindB("APT::Get::Remove",true) == false)
100 return _error
->Error(_("Packages need to be removed but remove is disabled."));
102 // Run the simulator ..
103 if (_config
->FindB("APT::Get::Simulate") == true)
105 pkgSimulate
PM(Cache
);
106 int status_fd
= _config
->FindI("APT::Status-Fd",-1);
107 pkgPackageManager::OrderResult Res
= PM
.DoInstall(status_fd
);
108 if (Res
== pkgPackageManager::Failed
)
110 if (Res
!= pkgPackageManager::Completed
)
111 return _error
->Error(_("Internal error, Ordering didn't finish"));
115 // Create the text record parser
116 pkgRecords
Recs(Cache
);
117 if (_error
->PendingError() == true)
120 // Create the download object
122 AcqTextStatus
Stat(ScreenWidth
,_config
->FindI("quiet",0));
123 if (_config
->FindB("APT::Get::Print-URIs", false) == true)
125 // force a hashsum for compatibility reasons
126 _config
->CndSet("Acquire::ForceHash", "md5sum");
128 else if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::Cache::Archives")) == false)
131 // Read the source list
132 if (Cache
.BuildSourceList() == false)
134 pkgSourceList
*List
= Cache
.GetSourceList();
136 // Create the package manager and prepare to download
137 SPtr
<pkgPackageManager
> PM
= _system
->CreatePM(Cache
);
138 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false ||
139 _error
->PendingError() == true)
142 // Display statistics
143 unsigned long long FetchBytes
= Fetcher
.FetchNeeded();
144 unsigned long long FetchPBytes
= Fetcher
.PartialPresent();
145 unsigned long long DebBytes
= Fetcher
.TotalNeeded();
146 if (DebBytes
!= Cache
->DebSize())
148 c0out
<< DebBytes
<< ',' << Cache
->DebSize() << std::endl
;
149 c0out
<< _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl
;
153 if (DebBytes
!= FetchBytes
)
154 //TRANSLATOR: The required space between number and unit is already included
155 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
156 ioprintf(c1out
,_("Need to get %sB/%sB of archives.\n"),
157 SizeToStr(FetchBytes
).c_str(),SizeToStr(DebBytes
).c_str());
158 else if (DebBytes
!= 0)
159 //TRANSLATOR: The required space between number and unit is already included
160 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
161 ioprintf(c1out
,_("Need to get %sB of archives.\n"),
162 SizeToStr(DebBytes
).c_str());
165 if (Cache
->UsrSize() >= 0)
166 //TRANSLATOR: The required space between number and unit is already included
167 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
168 ioprintf(c1out
,_("After this operation, %sB of additional disk space will be used.\n"),
169 SizeToStr(Cache
->UsrSize()).c_str());
171 //TRANSLATOR: The required space between number and unit is already included
172 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
173 ioprintf(c1out
,_("After this operation, %sB disk space will be freed.\n"),
174 SizeToStr(-1*Cache
->UsrSize()).c_str());
176 if (_error
->PendingError() == true)
179 /* Check for enough free space, but only if we are actually going to
181 if (_config
->FindB("APT::Get::Print-URIs") == false &&
182 _config
->FindB("APT::Get::Download",true) == true)
185 std::string OutputDir
= _config
->FindDir("Dir::Cache::Archives");
186 if (statvfs(OutputDir
.c_str(),&Buf
) != 0) {
187 if (errno
== EOVERFLOW
)
188 return _error
->WarningE("statvfs",_("Couldn't determine free space in %s"),
191 return _error
->Errno("statvfs",_("Couldn't determine free space in %s"),
193 } else if (unsigned(Buf
.f_bfree
) < (FetchBytes
- FetchPBytes
)/Buf
.f_bsize
)
196 if (statfs(OutputDir
.c_str(),&Stat
) != 0
197 #if HAVE_STRUCT_STATFS_F_TYPE
198 || unsigned(Stat
.f_type
) != RAMFS_MAGIC
201 return _error
->Error(_("You don't have enough free space in %s."),
207 if (_config
->FindI("quiet",0) >= 2 ||
208 _config
->FindB("APT::Get::Assume-Yes",false) == true)
210 if (Fail
== true && _config
->FindB("APT::Get::Force-Yes",false) == false)
211 return _error
->Error(_("There are problems and -y was used without --force-yes"));
214 if (Essential
== true && Safety
== true)
216 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
217 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
219 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
220 // careful with hard to type or special characters (like non-breaking spaces)
221 const char *Prompt
= _("Yes, do as I say!");
223 _("You are about to do something potentially harmful.\n"
224 "To continue type in the phrase '%s'\n"
227 if (AnalPrompt(Prompt
) == false)
229 c2out
<< _("Abort.") << std::endl
;
235 // Prompt to continue
236 if (Ask
== true || Fail
== true)
238 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
239 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
241 if (_config
->FindI("quiet",0) < 2 &&
242 _config
->FindB("APT::Get::Assume-Yes",false) == false)
244 c2out
<< _("Do you want to continue?") << std::flush
;
245 if (YnPrompt() == false)
247 c2out
<< _("Abort.") << std::endl
;
254 // Just print out the uris an exit if the --print-uris flag was used
255 if (_config
->FindB("APT::Get::Print-URIs") == true)
257 pkgAcquire::UriIterator I
= Fetcher
.UriBegin();
258 for (; I
!= Fetcher
.UriEnd(); ++I
)
259 std::cout
<< '\'' << I
->URI
<< "' " << flNotDir(I
->Owner
->DestFile
) << ' ' <<
260 I
->Owner
->FileSize
<< ' ' << I
->Owner
->HashSum() << std::endl
;
264 if (!CheckAuth(Fetcher
, true))
267 /* Unlock the dpkg lock if we are not going to be doing an install
269 if (_config
->FindB("APT::Get::Download-Only",false) == true)
275 bool Transient
= false;
276 if (_config
->FindB("APT::Get::Download",true) == false)
278 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
< Fetcher
.ItemsEnd();)
280 if ((*I
)->Local
== true)
286 // Close the item and check if it was found in cache
288 if ((*I
)->Complete
== false)
291 // Clear it out of the fetch list
293 I
= Fetcher
.ItemsBegin();
298 if (AcquireRun(Fetcher
, 0, &Failed
, &Transient
) == false)
301 /* If we are in no download mode and missing files and there were
302 'failures' then the user must specify -m. Furthermore, there
303 is no such thing as a transient error in no-download mode! */
304 if (Transient
== true &&
305 _config
->FindB("APT::Get::Download",true) == false)
311 if (_config
->FindB("APT::Get::Download-Only",false) == true)
313 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
314 return _error
->Error(_("Some files failed to download"));
315 c1out
<< _("Download complete and in download only mode") << std::endl
;
319 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
321 return _error
->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
324 if (Transient
== true && Failed
== true)
325 return _error
->Error(_("--fix-missing and media swapping is not currently supported"));
327 // Try to deal with missing package files
328 if (Failed
== true && PM
->FixMissing() == false)
330 c2out
<< _("Unable to correct missing packages.") << std::endl
;
331 return _error
->Error(_("Aborting install."));
335 int status_fd
= _config
->FindI("APT::Status-Fd",-1);
336 pkgPackageManager::OrderResult Res
= PM
->DoInstall(status_fd
);
337 if (Res
== pkgPackageManager::Failed
|| _error
->PendingError() == true)
339 if (Res
== pkgPackageManager::Completed
)
342 // Reload the fetcher object and loop again for media swapping
344 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false)
350 std::set
<std::string
> const disappearedPkgs
= PM
->GetDisappearedPackages();
351 if (disappearedPkgs
.empty() == true)
354 std::string disappear
;
355 for (std::set
<std::string
>::const_iterator d
= disappearedPkgs
.begin();
356 d
!= disappearedPkgs
.end(); ++d
)
357 disappear
.append(*d
).append(" ");
359 ShowList(c1out
, P_("The following package disappeared from your system as\n"
360 "all files have been overwritten by other packages:",
361 "The following packages disappeared from your system as\n"
362 "all files have been overwritten by other packages:", disappearedPkgs
.size()), disappear
, "");
363 c0out
<< _("Note: This is done automatically and on purpose by dpkg.") << std::endl
;
368 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
369 // ---------------------------------------------------------------------
370 /* Remove unused automatic packages */
371 bool DoAutomaticRemove(CacheFile
&Cache
)
373 bool Debug
= _config
->FindI("Debug::pkgAutoRemove",false);
374 bool doAutoRemove
= _config
->FindB("APT::Get::AutomaticRemove", false);
375 bool hideAutoRemove
= _config
->FindB("APT::Get::HideAutoRemove");
377 pkgDepCache::ActionGroup
group(*Cache
);
379 std::cout
<< "DoAutomaticRemove()" << std::endl
;
381 if (doAutoRemove
== true &&
382 _config
->FindB("APT::Get::Remove",true) == false)
384 c1out
<< _("We are not supposed to delete stuff, can't start "
385 "AutoRemover") << std::endl
;
389 bool purgePkgs
= _config
->FindB("APT::Get::Purge", false);
390 bool smallList
= (hideAutoRemove
== false &&
391 strcasecmp(_config
->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
393 unsigned long autoRemoveCount
= 0;
394 APT::PackageSet tooMuch
;
395 APT::PackageList autoRemoveList
;
396 // look over the cache to see what can be removed
397 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; ++J
)
399 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
400 if (Cache
[Pkg
].Garbage
)
402 if(Pkg
.CurrentVer() != 0 || Cache
[Pkg
].Install())
404 std::cout
<< "We could delete %s" << Pkg
.FullName(true).c_str() << std::endl
;
408 if(Pkg
.CurrentVer() != 0 &&
409 Pkg
->CurrentState
!= pkgCache::State::ConfigFiles
)
410 Cache
->MarkDelete(Pkg
, purgePkgs
, 0, false);
412 Cache
->MarkKeep(Pkg
, false, false);
416 if (hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
417 autoRemoveList
.insert(Pkg
);
418 // if the package is a new install and already garbage we don't need to
419 // install it in the first place, so nuke it instead of show it
420 if (Cache
[Pkg
].Install() == true && Pkg
.CurrentVer() == 0)
422 if (Pkg
.CandVersion() != 0)
424 Cache
->MarkDelete(Pkg
, false, 0, false);
426 // only show stuff in the list that is not yet marked for removal
427 else if(hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
433 // we could have removed a new dependency of a garbage package,
434 // so check if a reverse depends is broken and if so install it again.
435 if (tooMuch
.empty() == false && (Cache
->BrokenCount() != 0 || Cache
->PolicyBrokenCount() != 0))
440 for (APT::PackageSet::const_iterator Pkg
= tooMuch
.begin();
441 Pkg
!= tooMuch
.end() && Changed
== false; ++Pkg
)
445 for (pkgCache::PrvIterator Prv
= Cache
[Pkg
].CandidateVerIter(Cache
).ProvidesList();
446 Prv
.end() == false; ++Prv
)
447 too
.insert(Prv
.ParentPkg());
448 for (APT::PackageSet::const_iterator P
= too
.begin();
449 P
!= too
.end() && Changed
== false; ++P
) {
450 for (pkgCache::DepIterator R
= P
.RevDependsList();
451 R
.end() == false; ++R
)
453 if (R
.IsNegative() == true ||
454 Cache
->IsImportantDep(R
) == false)
456 pkgCache::PkgIterator N
= R
.ParentPkg();
457 if (N
.end() == true || (N
->CurrentVer
== 0 && (*Cache
)[N
].Install() == false))
460 std::clog
<< "Save " << Pkg
<< " as another installed garbage package depends on it" << std::endl
;
461 Cache
->MarkInstall(Pkg
, false, 0, false);
462 if (hideAutoRemove
== false)
470 } while (Changed
== true);
473 std::string autoremovelist
, autoremoveversions
;
474 if (smallList
== false && autoRemoveCount
!= 0)
476 for (APT::PackageList::const_iterator Pkg
= autoRemoveList
.begin(); Pkg
!= autoRemoveList
.end(); ++Pkg
)
478 if (Cache
[Pkg
].Garbage
== false)
480 autoremovelist
+= Pkg
.FullName(true) + " ";
481 autoremoveversions
+= std::string(Cache
[Pkg
].CandVersion
) + "\n";
485 // Now see if we had destroyed anything (if we had done anything)
486 if (Cache
->BrokenCount() != 0)
488 c1out
<< _("Hmm, seems like the AutoRemover destroyed something which really\n"
489 "shouldn't happen. Please file a bug report against apt.") << std::endl
;
491 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
493 ShowBroken(c1out
,Cache
,false);
495 return _error
->Error(_("Internal Error, AutoRemover broke stuff"));
498 // if we don't remove them, we should show them!
499 if (doAutoRemove
== false && (autoremovelist
.empty() == false || autoRemoveCount
!= 0))
501 if (smallList
== false)
502 ShowList(c1out
, P_("The following package was automatically installed and is no longer required:",
503 "The following packages were automatically installed and are no longer required:",
504 autoRemoveCount
), autoremovelist
, autoremoveversions
);
506 ioprintf(c1out
, P_("%lu package was automatically installed and is no longer required.\n",
507 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount
), autoRemoveCount
);
508 c1out
<< P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount
) << std::endl
;
513 // DoCacheManipulationFromCommandLine /*{{{*/
514 static const unsigned short MOD_REMOVE
= 1;
515 static const unsigned short MOD_INSTALL
= 2;
517 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
)
519 std::map
<unsigned short, APT::VersionSet
> verset
;
520 return DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
);
522 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
,
523 std::map
<unsigned short, APT::VersionSet
> &verset
)
526 // Enter the special broken fixing mode if the user specified arguments
527 bool BrokenFix
= false;
528 if (Cache
->BrokenCount() != 0)
531 SPtr
<pkgProblemResolver
> Fix
;
532 if (_config
->FindB("APT::Get::CallResolver", true) == true)
533 Fix
= new pkgProblemResolver(Cache
);
535 unsigned short fallback
= MOD_INSTALL
;
536 if (strcasecmp(CmdL
.FileList
[0],"remove") == 0)
537 fallback
= MOD_REMOVE
;
538 else if (strcasecmp(CmdL
.FileList
[0], "purge") == 0)
540 _config
->Set("APT::Get::Purge", true);
541 fallback
= MOD_REMOVE
;
543 else if (strcasecmp(CmdL
.FileList
[0], "autoremove") == 0)
545 _config
->Set("APT::Get::AutomaticRemove", "true");
546 fallback
= MOD_REMOVE
;
549 std::list
<APT::VersionSet::Modifier
> mods
;
550 mods
.push_back(APT::VersionSet::Modifier(MOD_INSTALL
, "+",
551 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::CANDIDATE
));
552 mods
.push_back(APT::VersionSet::Modifier(MOD_REMOVE
, "-",
553 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::NEWEST
));
554 CacheSetHelperAPTGet
helper(c0out
);
555 verset
= APT::VersionSet::GroupedFromCommandLine(Cache
,
556 CmdL
.FileList
+ 1, mods
, fallback
, helper
);
558 if (_error
->PendingError() == true)
560 helper
.showVirtualPackageErrors(Cache
);
565 TryToInstall
InstallAction(Cache
, Fix
, BrokenFix
);
566 TryToRemove
RemoveAction(Cache
, Fix
);
568 // new scope for the ActionGroup
570 pkgDepCache::ActionGroup
group(Cache
);
571 unsigned short const order
[] = { MOD_REMOVE
, MOD_INSTALL
, 0 };
573 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
575 if (order
[i
] == MOD_INSTALL
)
576 InstallAction
= std::for_each(verset
[MOD_INSTALL
].begin(), verset
[MOD_INSTALL
].end(), InstallAction
);
577 else if (order
[i
] == MOD_REMOVE
)
578 RemoveAction
= std::for_each(verset
[MOD_REMOVE
].begin(), verset
[MOD_REMOVE
].end(), RemoveAction
);
581 if (Fix
!= NULL
&& _config
->FindB("APT::Get::AutoSolving", true) == true)
583 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
585 if (order
[i
] != MOD_INSTALL
)
587 InstallAction
.propergateReleaseCandiateSwitching(helper
.selectedByRelease
, c0out
);
588 InstallAction
.doAutoInstall();
592 if (_error
->PendingError() == true)
597 /* If we are in the Broken fixing mode we do not attempt to fix the
598 problems. This is if the user invoked install without -f and gave
600 if (BrokenFix
== true && Cache
->BrokenCount() != 0)
602 c1out
<< _("You might want to run 'apt-get -f install' to correct these:") << std::endl
;
603 ShowBroken(c1out
,Cache
,false);
604 return _error
->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
609 // Call the scored problem resolver
613 // Now we check the state of the packages,
614 if (Cache
->BrokenCount() != 0)
617 _("Some packages could not be installed. This may mean that you have\n"
618 "requested an impossible situation or if you are using the unstable\n"
619 "distribution that some required packages have not yet been created\n"
620 "or been moved out of Incoming.") << std::endl
;
626 _("Since you only requested a single operation it is extremely likely that\n"
627 "the package is simply not installable and a bug report against\n"
628 "that package should be filed.") << std::endl;
632 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
634 ShowBroken(c1out
,Cache
,false);
635 if (_error
->PendingError() == true)
638 return _error
->Error(_("Broken packages"));
641 if (!DoAutomaticRemove(Cache
))
644 // if nothing changed in the cache, but only the automark information
645 // we write the StateFile here, otherwise it will be written in
647 if (InstallAction
.AutoMarkChanged
> 0 &&
648 Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
649 Cache
->BadCount() == 0 &&
650 _config
->FindB("APT::Get::Simulate",false) == false)
651 Cache
->writeStateFile(NULL
);
656 // DoInstall - Install packages from the command line /*{{{*/
657 // ---------------------------------------------------------------------
658 /* Install named packages */
659 bool DoInstall(CommandLine
&CmdL
)
662 if (Cache
.OpenForInstall() == false ||
663 Cache
.CheckDeps(CmdL
.FileSize() != 1) == false)
666 std::map
<unsigned short, APT::VersionSet
> verset
;
668 if(!DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
))
671 /* Print out a list of packages that are going to be installed extra
672 to what the user asked */
673 if (Cache
->InstCount() != verset
[MOD_INSTALL
].size())
676 std::string VersionsList
;
677 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
679 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
680 if ((*Cache
)[I
].Install() == false)
682 pkgCache::VerIterator Cand
= Cache
[I
].CandidateVerIter(Cache
);
684 if (verset
[MOD_INSTALL
].find(Cand
) != verset
[MOD_INSTALL
].end())
687 List
+= I
.FullName(true) + " ";
688 VersionsList
+= std::string(Cache
[I
].CandVersion
) + "\n";
691 ShowList(c1out
,_("The following extra packages will be installed:"),List
,VersionsList
);
694 /* Print out a list of suggested and recommended packages */
696 std::string SuggestsList
, RecommendsList
;
697 std::string SuggestsVersions
, RecommendsVersions
;
698 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
700 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
702 /* Just look at the ones we want to install */
703 if ((*Cache
)[Pkg
].Install() == false)
706 // get the recommends/suggests for the candidate ver
707 pkgCache::VerIterator CV
= (*Cache
)[Pkg
].CandidateVerIter(*Cache
);
708 for (pkgCache::DepIterator D
= CV
.DependsList(); D
.end() == false; )
710 pkgCache::DepIterator Start
;
711 pkgCache::DepIterator End
;
712 D
.GlobOr(Start
,End
); // advances D
714 // FIXME: we really should display a or-group as a or-group to the user
715 // the problem is that ShowList is incapable of doing this
716 std::string RecommendsOrList
,RecommendsOrVersions
;
717 std::string SuggestsOrList
,SuggestsOrVersions
;
718 bool foundInstalledInOrGroup
= false;
721 /* Skip if package is installed already, or is about to be */
722 std::string target
= Start
.TargetPkg().FullName(true) + " ";
723 pkgCache::PkgIterator
const TarPkg
= Start
.TargetPkg();
724 if (TarPkg
->SelectedState
== pkgCache::State::Install
||
725 TarPkg
->SelectedState
== pkgCache::State::Hold
||
726 Cache
[Start
.TargetPkg()].Install())
728 foundInstalledInOrGroup
=true;
732 /* Skip if we already saw it */
733 if (int(SuggestsList
.find(target
)) != -1 || int(RecommendsList
.find(target
)) != -1)
735 foundInstalledInOrGroup
=true;
739 // this is a dep on a virtual pkg, check if any package that provides it
740 // should be installed
741 if(Start
.TargetPkg().ProvidesList() != 0)
743 pkgCache::PrvIterator I
= Start
.TargetPkg().ProvidesList();
744 for (; I
.end() == false; ++I
)
746 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
747 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer() &&
748 Pkg
.CurrentVer() != 0)
749 foundInstalledInOrGroup
=true;
753 if (Start
->Type
== pkgCache::Dep::Suggests
)
755 SuggestsOrList
+= target
;
756 SuggestsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
759 if (Start
->Type
== pkgCache::Dep::Recommends
)
761 RecommendsOrList
+= target
;
762 RecommendsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
770 if(foundInstalledInOrGroup
== false)
772 RecommendsList
+= RecommendsOrList
;
773 RecommendsVersions
+= RecommendsOrVersions
;
774 SuggestsList
+= SuggestsOrList
;
775 SuggestsVersions
+= SuggestsOrVersions
;
781 ShowList(c1out
,_("Suggested packages:"),SuggestsList
,SuggestsVersions
);
782 ShowList(c1out
,_("Recommended packages:"),RecommendsList
,RecommendsVersions
);
786 // See if we need to prompt
787 // FIXME: check if really the packages in the set are going to be installed
788 if (Cache
->InstCount() == verset
[MOD_INSTALL
].size() && Cache
->DelCount() == 0)
789 return InstallPackages(Cache
,false,false);
791 return InstallPackages(Cache
,false);