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"));
97 // InstallPackages - Actually download and install the packages /*{{{*/
98 // ---------------------------------------------------------------------
99 /* This displays the informative messages describing what is going to
100 happen and then calls the download routines */
101 bool InstallPackages(CacheFile
&Cache
,bool ShwKept
,bool Ask
, bool Safety
)
103 if (_config
->FindB("APT::Get::Purge",false) == true)
105 pkgCache::PkgIterator I
= Cache
->PkgBegin();
106 for (; I
.end() == false; ++I
)
108 if (I
.Purge() == false && Cache
[I
].Mode
== pkgDepCache::ModeDelete
)
109 Cache
->MarkDelete(I
,true);
114 bool Essential
= false;
116 // Show all the various warning indicators
117 ShowDel(c1out
,Cache
);
118 ShowNew(c1out
,Cache
);
120 ShowKept(c1out
,Cache
);
121 Fail
|= !ShowHold(c1out
,Cache
);
122 if (_config
->FindB("APT::Get::Show-Upgraded",true) == true)
123 ShowUpgraded(c1out
,Cache
);
124 Fail
|= !ShowDowngraded(c1out
,Cache
);
125 if (_config
->FindB("APT::Get::Download-Only",false) == false)
126 Essential
= !ShowEssential(c1out
,Cache
);
131 if (Cache
->BrokenCount() != 0)
133 ShowBroken(c1out
,Cache
,false);
134 return _error
->Error(_("Internal error, InstallPackages was called with broken packages!"));
137 if (Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
138 Cache
->BadCount() == 0)
142 if (Cache
->DelCount() != 0 && _config
->FindB("APT::Get::Remove",true) == false)
143 return _error
->Error(_("Packages need to be removed but remove is disabled."));
145 // Run the simulator ..
146 if (_config
->FindB("APT::Get::Simulate") == true)
148 pkgSimulate
PM(Cache
);
149 int status_fd
= _config
->FindI("APT::Status-Fd",-1);
150 pkgPackageManager::OrderResult Res
= PM
.DoInstall(status_fd
);
151 if (Res
== pkgPackageManager::Failed
)
153 if (Res
!= pkgPackageManager::Completed
)
154 return _error
->Error(_("Internal error, Ordering didn't finish"));
158 // Create the text record parser
159 pkgRecords
Recs(Cache
);
160 if (_error
->PendingError() == true)
163 // Create the download object
165 AcqTextStatus
Stat(ScreenWidth
,_config
->FindI("quiet",0));
166 if (_config
->FindB("APT::Get::Print-URIs", false) == true)
168 // force a hashsum for compatibility reasons
169 _config
->CndSet("Acquire::ForceHash", "md5sum");
171 else if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::Cache::Archives")) == false)
174 // Read the source list
175 if (Cache
.BuildSourceList() == false)
177 pkgSourceList
*List
= Cache
.GetSourceList();
179 // Create the package manager and prepare to download
180 SPtr
<pkgPackageManager
> PM
= _system
->CreatePM(Cache
);
181 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false ||
182 _error
->PendingError() == true)
185 // Display statistics
186 unsigned long long FetchBytes
= Fetcher
.FetchNeeded();
187 unsigned long long FetchPBytes
= Fetcher
.PartialPresent();
188 unsigned long long DebBytes
= Fetcher
.TotalNeeded();
189 if (DebBytes
!= Cache
->DebSize())
191 c0out
<< DebBytes
<< ',' << Cache
->DebSize() << std::endl
;
192 c0out
<< _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl
;
196 if (DebBytes
!= FetchBytes
)
197 //TRANSLATOR: The required space between number and unit is already included
198 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
199 ioprintf(c1out
,_("Need to get %sB/%sB of archives.\n"),
200 SizeToStr(FetchBytes
).c_str(),SizeToStr(DebBytes
).c_str());
201 else if (DebBytes
!= 0)
202 //TRANSLATOR: The required space between number and unit is already included
203 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
204 ioprintf(c1out
,_("Need to get %sB of archives.\n"),
205 SizeToStr(DebBytes
).c_str());
208 if (Cache
->UsrSize() >= 0)
209 //TRANSLATOR: The required space between number and unit is already included
210 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
211 ioprintf(c1out
,_("After this operation, %sB of additional disk space will be used.\n"),
212 SizeToStr(Cache
->UsrSize()).c_str());
214 //TRANSLATOR: The required space between number and unit is already included
215 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
216 ioprintf(c1out
,_("After this operation, %sB disk space will be freed.\n"),
217 SizeToStr(-1*Cache
->UsrSize()).c_str());
219 if (_error
->PendingError() == true)
222 /* Check for enough free space, but only if we are actually going to
224 if (_config
->FindB("APT::Get::Print-URIs") == false &&
225 _config
->FindB("APT::Get::Download",true) == true)
228 std::string OutputDir
= _config
->FindDir("Dir::Cache::Archives");
229 if (statvfs(OutputDir
.c_str(),&Buf
) != 0) {
230 if (errno
== EOVERFLOW
)
231 return _error
->WarningE("statvfs",_("Couldn't determine free space in %s"),
234 return _error
->Errno("statvfs",_("Couldn't determine free space in %s"),
236 } else if (unsigned(Buf
.f_bfree
) < (FetchBytes
- FetchPBytes
)/Buf
.f_bsize
)
239 if (statfs(OutputDir
.c_str(),&Stat
) != 0
240 #if HAVE_STRUCT_STATFS_F_TYPE
241 || unsigned(Stat
.f_type
) != RAMFS_MAGIC
244 return _error
->Error(_("You don't have enough free space in %s."),
250 if (_config
->FindI("quiet",0) >= 2 ||
251 _config
->FindB("APT::Get::Assume-Yes",false) == true)
253 if (Fail
== true && _config
->FindB("APT::Get::Force-Yes",false) == false)
254 return _error
->Error(_("There are problems and -y was used without --force-yes"));
257 if (Essential
== true && Safety
== true)
259 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
260 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
262 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
263 // careful with hard to type or special characters (like non-breaking spaces)
264 const char *Prompt
= _("Yes, do as I say!");
266 _("You are about to do something potentially harmful.\n"
267 "To continue type in the phrase '%s'\n"
270 if (AnalPrompt(Prompt
) == false)
272 c2out
<< _("Abort.") << std::endl
;
278 // Prompt to continue
279 if (Ask
== true || Fail
== true)
281 if (_config
->FindB("APT::Get::Trivial-Only",false) == true)
282 return _error
->Error(_("Trivial Only specified but this is not a trivial operation."));
284 if (_config
->FindI("quiet",0) < 2 &&
285 _config
->FindB("APT::Get::Assume-Yes",false) == false)
287 c2out
<< _("Do you want to continue?") << std::flush
;
288 if (YnPrompt() == false)
290 c2out
<< _("Abort.") << std::endl
;
297 // Just print out the uris an exit if the --print-uris flag was used
298 if (_config
->FindB("APT::Get::Print-URIs") == true)
300 pkgAcquire::UriIterator I
= Fetcher
.UriBegin();
301 for (; I
!= Fetcher
.UriEnd(); ++I
)
302 std::cout
<< '\'' << I
->URI
<< "' " << flNotDir(I
->Owner
->DestFile
) << ' ' <<
303 I
->Owner
->FileSize
<< ' ' << I
->Owner
->HashSum() << std::endl
;
307 if (!CheckAuth(Fetcher
))
310 /* Unlock the dpkg lock if we are not going to be doing an install
312 if (_config
->FindB("APT::Get::Download-Only",false) == true)
318 bool Transient
= false;
319 if (_config
->FindB("APT::Get::Download",true) == false)
321 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
< Fetcher
.ItemsEnd();)
323 if ((*I
)->Local
== true)
329 // Close the item and check if it was found in cache
331 if ((*I
)->Complete
== false)
334 // Clear it out of the fetch list
336 I
= Fetcher
.ItemsBegin();
340 if (Fetcher
.Run() == pkgAcquire::Failed
)
345 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
!= Fetcher
.ItemsEnd(); ++I
)
347 if ((*I
)->Status
== pkgAcquire::Item::StatDone
&&
348 (*I
)->Complete
== true)
351 if ((*I
)->Status
== pkgAcquire::Item::StatIdle
)
358 fprintf(stderr
,_("Failed to fetch %s %s\n"),(*I
)->DescURI().c_str(),
359 (*I
)->ErrorText
.c_str());
363 /* If we are in no download mode and missing files and there were
364 'failures' then the user must specify -m. Furthermore, there
365 is no such thing as a transient error in no-download mode! */
366 if (Transient
== true &&
367 _config
->FindB("APT::Get::Download",true) == false)
373 if (_config
->FindB("APT::Get::Download-Only",false) == true)
375 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
376 return _error
->Error(_("Some files failed to download"));
377 c1out
<< _("Download complete and in download only mode") << std::endl
;
381 if (Failed
== true && _config
->FindB("APT::Get::Fix-Missing",false) == false)
383 return _error
->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
386 if (Transient
== true && Failed
== true)
387 return _error
->Error(_("--fix-missing and media swapping is not currently supported"));
389 // Try to deal with missing package files
390 if (Failed
== true && PM
->FixMissing() == false)
392 c2out
<< _("Unable to correct missing packages.") << std::endl
;
393 return _error
->Error(_("Aborting install."));
397 int status_fd
= _config
->FindI("APT::Status-Fd",-1);
398 pkgPackageManager::OrderResult Res
= PM
->DoInstall(status_fd
);
399 if (Res
== pkgPackageManager::Failed
|| _error
->PendingError() == true)
401 if (Res
== pkgPackageManager::Completed
)
404 // Reload the fetcher object and loop again for media swapping
406 if (PM
->GetArchives(&Fetcher
,List
,&Recs
) == false)
412 std::set
<std::string
> const disappearedPkgs
= PM
->GetDisappearedPackages();
413 if (disappearedPkgs
.empty() == true)
416 std::string disappear
;
417 for (std::set
<std::string
>::const_iterator d
= disappearedPkgs
.begin();
418 d
!= disappearedPkgs
.end(); ++d
)
419 disappear
.append(*d
).append(" ");
421 ShowList(c1out
, P_("The following package disappeared from your system as\n"
422 "all files have been overwritten by other packages:",
423 "The following packages disappeared from your system as\n"
424 "all files have been overwritten by other packages:", disappearedPkgs
.size()), disappear
, "");
425 c0out
<< _("Note: This is done automatically and on purpose by dpkg.") << std::endl
;
430 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
431 // ---------------------------------------------------------------------
432 /* Remove unused automatic packages */
433 bool DoAutomaticRemove(CacheFile
&Cache
)
435 bool Debug
= _config
->FindI("Debug::pkgAutoRemove",false);
436 bool doAutoRemove
= _config
->FindB("APT::Get::AutomaticRemove", false);
437 bool hideAutoRemove
= _config
->FindB("APT::Get::HideAutoRemove");
439 pkgDepCache::ActionGroup
group(*Cache
);
441 std::cout
<< "DoAutomaticRemove()" << std::endl
;
443 if (doAutoRemove
== true &&
444 _config
->FindB("APT::Get::Remove",true) == false)
446 c1out
<< _("We are not supposed to delete stuff, can't start "
447 "AutoRemover") << std::endl
;
451 bool purgePkgs
= _config
->FindB("APT::Get::Purge", false);
452 bool smallList
= (hideAutoRemove
== false &&
453 strcasecmp(_config
->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
455 unsigned long autoRemoveCount
= 0;
456 APT::PackageSet tooMuch
;
457 APT::PackageList autoRemoveList
;
458 // look over the cache to see what can be removed
459 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; ++J
)
461 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
462 if (Cache
[Pkg
].Garbage
)
464 if(Pkg
.CurrentVer() != 0 || Cache
[Pkg
].Install())
466 std::cout
<< "We could delete %s" << Pkg
.FullName(true).c_str() << std::endl
;
470 if(Pkg
.CurrentVer() != 0 &&
471 Pkg
->CurrentState
!= pkgCache::State::ConfigFiles
)
472 Cache
->MarkDelete(Pkg
, purgePkgs
, 0, false);
474 Cache
->MarkKeep(Pkg
, false, false);
478 if (hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
479 autoRemoveList
.insert(Pkg
);
480 // if the package is a new install and already garbage we don't need to
481 // install it in the first place, so nuke it instead of show it
482 if (Cache
[Pkg
].Install() == true && Pkg
.CurrentVer() == 0)
484 if (Pkg
.CandVersion() != 0)
486 Cache
->MarkDelete(Pkg
, false, 0, false);
488 // only show stuff in the list that is not yet marked for removal
489 else if(hideAutoRemove
== false && Cache
[Pkg
].Delete() == false)
495 // we could have removed a new dependency of a garbage package,
496 // so check if a reverse depends is broken and if so install it again.
497 if (tooMuch
.empty() == false && (Cache
->BrokenCount() != 0 || Cache
->PolicyBrokenCount() != 0))
502 for (APT::PackageSet::const_iterator Pkg
= tooMuch
.begin();
503 Pkg
!= tooMuch
.end() && Changed
== false; ++Pkg
)
507 for (pkgCache::PrvIterator Prv
= Cache
[Pkg
].CandidateVerIter(Cache
).ProvidesList();
508 Prv
.end() == false; ++Prv
)
509 too
.insert(Prv
.ParentPkg());
510 for (APT::PackageSet::const_iterator P
= too
.begin();
511 P
!= too
.end() && Changed
== false; ++P
) {
512 for (pkgCache::DepIterator R
= P
.RevDependsList();
513 R
.end() == false; ++R
)
515 if (R
.IsNegative() == true ||
516 Cache
->IsImportantDep(R
) == false)
518 pkgCache::PkgIterator N
= R
.ParentPkg();
519 if (N
.end() == true || (N
->CurrentVer
== 0 && (*Cache
)[N
].Install() == false))
522 std::clog
<< "Save " << Pkg
<< " as another installed garbage package depends on it" << std::endl
;
523 Cache
->MarkInstall(Pkg
, false, 0, false);
524 if (hideAutoRemove
== false)
532 } while (Changed
== true);
535 std::string autoremovelist
, autoremoveversions
;
536 if (smallList
== false && autoRemoveCount
!= 0)
538 for (APT::PackageList::const_iterator Pkg
= autoRemoveList
.begin(); Pkg
!= autoRemoveList
.end(); ++Pkg
)
540 if (Cache
[Pkg
].Garbage
== false)
542 autoremovelist
+= Pkg
.FullName(true) + " ";
543 autoremoveversions
+= std::string(Cache
[Pkg
].CandVersion
) + "\n";
547 // Now see if we had destroyed anything (if we had done anything)
548 if (Cache
->BrokenCount() != 0)
550 c1out
<< _("Hmm, seems like the AutoRemover destroyed something which really\n"
551 "shouldn't happen. Please file a bug report against apt.") << std::endl
;
553 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
555 ShowBroken(c1out
,Cache
,false);
557 return _error
->Error(_("Internal Error, AutoRemover broke stuff"));
560 // if we don't remove them, we should show them!
561 if (doAutoRemove
== false && (autoremovelist
.empty() == false || autoRemoveCount
!= 0))
563 if (smallList
== false)
564 ShowList(c1out
, P_("The following package was automatically installed and is no longer required:",
565 "The following packages were automatically installed and are no longer required:",
566 autoRemoveCount
), autoremovelist
, autoremoveversions
);
568 ioprintf(c1out
, P_("%lu package was automatically installed and is no longer required.\n",
569 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount
), autoRemoveCount
);
570 c1out
<< P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount
) << std::endl
;
575 // DoCacheManipulationFromCommandLine /*{{{*/
576 static const unsigned short MOD_REMOVE
= 1;
577 static const unsigned short MOD_INSTALL
= 2;
579 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
)
581 std::map
<unsigned short, APT::VersionSet
> verset
;
582 return DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
);
584 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
,
585 std::map
<unsigned short, APT::VersionSet
> &verset
)
588 // Enter the special broken fixing mode if the user specified arguments
589 bool BrokenFix
= false;
590 if (Cache
->BrokenCount() != 0)
593 SPtr
<pkgProblemResolver
> Fix
;
594 if (_config
->FindB("APT::Get::CallResolver", true) == true)
595 Fix
= new pkgProblemResolver(Cache
);
597 unsigned short fallback
= MOD_INSTALL
;
598 if (strcasecmp(CmdL
.FileList
[0],"remove") == 0)
599 fallback
= MOD_REMOVE
;
600 else if (strcasecmp(CmdL
.FileList
[0], "purge") == 0)
602 _config
->Set("APT::Get::Purge", true);
603 fallback
= MOD_REMOVE
;
605 else if (strcasecmp(CmdL
.FileList
[0], "autoremove") == 0)
607 _config
->Set("APT::Get::AutomaticRemove", "true");
608 fallback
= MOD_REMOVE
;
611 std::list
<APT::VersionSet::Modifier
> mods
;
612 mods
.push_back(APT::VersionSet::Modifier(MOD_INSTALL
, "+",
613 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::CANDIDATE
));
614 mods
.push_back(APT::VersionSet::Modifier(MOD_REMOVE
, "-",
615 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::NEWEST
));
616 CacheSetHelperAPTGet
helper(c0out
);
617 verset
= APT::VersionSet::GroupedFromCommandLine(Cache
,
618 CmdL
.FileList
+ 1, mods
, fallback
, helper
);
620 if (_error
->PendingError() == true)
622 helper
.showVirtualPackageErrors(Cache
);
627 TryToInstall
InstallAction(Cache
, Fix
, BrokenFix
);
628 TryToRemove
RemoveAction(Cache
, Fix
);
630 // new scope for the ActionGroup
632 pkgDepCache::ActionGroup
group(Cache
);
633 unsigned short const order
[] = { MOD_REMOVE
, MOD_INSTALL
, 0 };
635 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
637 if (order
[i
] == MOD_INSTALL
)
638 InstallAction
= std::for_each(verset
[MOD_INSTALL
].begin(), verset
[MOD_INSTALL
].end(), InstallAction
);
639 else if (order
[i
] == MOD_REMOVE
)
640 RemoveAction
= std::for_each(verset
[MOD_REMOVE
].begin(), verset
[MOD_REMOVE
].end(), RemoveAction
);
643 if (Fix
!= NULL
&& _config
->FindB("APT::Get::AutoSolving", true) == true)
645 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
647 if (order
[i
] != MOD_INSTALL
)
649 InstallAction
.propergateReleaseCandiateSwitching(helper
.selectedByRelease
, c0out
);
650 InstallAction
.doAutoInstall();
654 if (_error
->PendingError() == true)
659 /* If we are in the Broken fixing mode we do not attempt to fix the
660 problems. This is if the user invoked install without -f and gave
662 if (BrokenFix
== true && Cache
->BrokenCount() != 0)
664 c1out
<< _("You might want to run 'apt-get -f install' to correct these:") << std::endl
;
665 ShowBroken(c1out
,Cache
,false);
666 return _error
->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
671 // Call the scored problem resolver
675 // Now we check the state of the packages,
676 if (Cache
->BrokenCount() != 0)
679 _("Some packages could not be installed. This may mean that you have\n"
680 "requested an impossible situation or if you are using the unstable\n"
681 "distribution that some required packages have not yet been created\n"
682 "or been moved out of Incoming.") << std::endl
;
688 _("Since you only requested a single operation it is extremely likely that\n"
689 "the package is simply not installable and a bug report against\n"
690 "that package should be filed.") << std::endl;
694 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
696 ShowBroken(c1out
,Cache
,false);
697 if (_error
->PendingError() == true)
700 return _error
->Error(_("Broken packages"));
703 if (!DoAutomaticRemove(Cache
))
706 // if nothing changed in the cache, but only the automark information
707 // we write the StateFile here, otherwise it will be written in
709 if (InstallAction
.AutoMarkChanged
> 0 &&
710 Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
711 Cache
->BadCount() == 0 &&
712 _config
->FindB("APT::Get::Simulate",false) == false)
713 Cache
->writeStateFile(NULL
);
718 // DoInstall - Install packages from the command line /*{{{*/
719 // ---------------------------------------------------------------------
720 /* Install named packages */
721 bool DoInstall(CommandLine
&CmdL
)
724 if (Cache
.OpenForInstall() == false ||
725 Cache
.CheckDeps(CmdL
.FileSize() != 1) == false)
728 std::map
<unsigned short, APT::VersionSet
> verset
;
730 if(!DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
))
733 /* Print out a list of packages that are going to be installed extra
734 to what the user asked */
735 if (Cache
->InstCount() != verset
[MOD_INSTALL
].size())
738 std::string VersionsList
;
739 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
741 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
742 if ((*Cache
)[I
].Install() == false)
744 pkgCache::VerIterator Cand
= Cache
[I
].CandidateVerIter(Cache
);
746 if (verset
[MOD_INSTALL
].find(Cand
) != verset
[MOD_INSTALL
].end())
749 List
+= I
.FullName(true) + " ";
750 VersionsList
+= std::string(Cache
[I
].CandVersion
) + "\n";
753 ShowList(c1out
,_("The following extra packages will be installed:"),List
,VersionsList
);
756 /* Print out a list of suggested and recommended packages */
758 std::string SuggestsList
, RecommendsList
;
759 std::string SuggestsVersions
, RecommendsVersions
;
760 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
762 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
764 /* Just look at the ones we want to install */
765 if ((*Cache
)[Pkg
].Install() == false)
768 // get the recommends/suggests for the candidate ver
769 pkgCache::VerIterator CV
= (*Cache
)[Pkg
].CandidateVerIter(*Cache
);
770 for (pkgCache::DepIterator D
= CV
.DependsList(); D
.end() == false; )
772 pkgCache::DepIterator Start
;
773 pkgCache::DepIterator End
;
774 D
.GlobOr(Start
,End
); // advances D
776 // FIXME: we really should display a or-group as a or-group to the user
777 // the problem is that ShowList is incapable of doing this
778 std::string RecommendsOrList
,RecommendsOrVersions
;
779 std::string SuggestsOrList
,SuggestsOrVersions
;
780 bool foundInstalledInOrGroup
= false;
783 /* Skip if package is installed already, or is about to be */
784 std::string target
= Start
.TargetPkg().FullName(true) + " ";
785 pkgCache::PkgIterator
const TarPkg
= Start
.TargetPkg();
786 if (TarPkg
->SelectedState
== pkgCache::State::Install
||
787 TarPkg
->SelectedState
== pkgCache::State::Hold
||
788 Cache
[Start
.TargetPkg()].Install())
790 foundInstalledInOrGroup
=true;
794 /* Skip if we already saw it */
795 if (int(SuggestsList
.find(target
)) != -1 || int(RecommendsList
.find(target
)) != -1)
797 foundInstalledInOrGroup
=true;
801 // this is a dep on a virtual pkg, check if any package that provides it
802 // should be installed
803 if(Start
.TargetPkg().ProvidesList() != 0)
805 pkgCache::PrvIterator I
= Start
.TargetPkg().ProvidesList();
806 for (; I
.end() == false; ++I
)
808 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
809 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer() &&
810 Pkg
.CurrentVer() != 0)
811 foundInstalledInOrGroup
=true;
815 if (Start
->Type
== pkgCache::Dep::Suggests
)
817 SuggestsOrList
+= target
;
818 SuggestsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
821 if (Start
->Type
== pkgCache::Dep::Recommends
)
823 RecommendsOrList
+= target
;
824 RecommendsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
832 if(foundInstalledInOrGroup
== false)
834 RecommendsList
+= RecommendsOrList
;
835 RecommendsVersions
+= RecommendsOrVersions
;
836 SuggestsList
+= SuggestsOrList
;
837 SuggestsVersions
+= SuggestsOrVersions
;
843 ShowList(c1out
,_("Suggested packages:"),SuggestsList
,SuggestsVersions
);
844 ShowList(c1out
,_("Recommended packages:"),RecommendsList
,RecommendsVersions
);
848 // See if we need to prompt
849 // FIXME: check if really the packages in the set are going to be installed
850 if (Cache
->InstCount() == verset
[MOD_INSTALL
].size() && Cache
->DelCount() == 0)
851 return InstallPackages(Cache
,false,false);
853 return InstallPackages(Cache
,false);