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
;
580 static const unsigned short MOD_REMOVE
= 1;
581 static const unsigned short MOD_INSTALL
= 2;
583 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
)
585 std::map
<unsigned short, APT::VersionSet
> verset
;
586 return DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
);
589 bool DoCacheManipulationFromCommandLine(CommandLine
&CmdL
, CacheFile
&Cache
,
590 std::map
<unsigned short, APT::VersionSet
> &verset
)
593 // Enter the special broken fixing mode if the user specified arguments
594 bool BrokenFix
= false;
595 if (Cache
->BrokenCount() != 0)
598 SPtr
<pkgProblemResolver
> Fix
;
599 if (_config
->FindB("APT::Get::CallResolver", true) == true)
600 Fix
= new pkgProblemResolver(Cache
);
602 unsigned short fallback
= MOD_INSTALL
;
603 if (strcasecmp(CmdL
.FileList
[0],"remove") == 0)
604 fallback
= MOD_REMOVE
;
605 else if (strcasecmp(CmdL
.FileList
[0], "purge") == 0)
607 _config
->Set("APT::Get::Purge", true);
608 fallback
= MOD_REMOVE
;
610 else if (strcasecmp(CmdL
.FileList
[0], "autoremove") == 0)
612 _config
->Set("APT::Get::AutomaticRemove", "true");
613 fallback
= MOD_REMOVE
;
616 std::list
<APT::VersionSet::Modifier
> mods
;
617 mods
.push_back(APT::VersionSet::Modifier(MOD_INSTALL
, "+",
618 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::CANDIDATE
));
619 mods
.push_back(APT::VersionSet::Modifier(MOD_REMOVE
, "-",
620 APT::VersionSet::Modifier::POSTFIX
, APT::VersionSet::NEWEST
));
621 CacheSetHelperAPTGet
helper(c0out
);
622 verset
= APT::VersionSet::GroupedFromCommandLine(Cache
,
623 CmdL
.FileList
+ 1, mods
, fallback
, helper
);
625 if (_error
->PendingError() == true)
627 helper
.showVirtualPackageErrors(Cache
);
632 TryToInstall
InstallAction(Cache
, Fix
, BrokenFix
);
633 TryToRemove
RemoveAction(Cache
, Fix
);
635 // new scope for the ActionGroup
637 pkgDepCache::ActionGroup
group(Cache
);
638 unsigned short const order
[] = { MOD_REMOVE
, MOD_INSTALL
, 0 };
640 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
642 if (order
[i
] == MOD_INSTALL
)
643 InstallAction
= std::for_each(verset
[MOD_INSTALL
].begin(), verset
[MOD_INSTALL
].end(), InstallAction
);
644 else if (order
[i
] == MOD_REMOVE
)
645 RemoveAction
= std::for_each(verset
[MOD_REMOVE
].begin(), verset
[MOD_REMOVE
].end(), RemoveAction
);
648 if (Fix
!= NULL
&& _config
->FindB("APT::Get::AutoSolving", true) == true)
650 for (unsigned short i
= 0; order
[i
] != 0; ++i
)
652 if (order
[i
] != MOD_INSTALL
)
654 InstallAction
.propergateReleaseCandiateSwitching(helper
.selectedByRelease
, c0out
);
655 InstallAction
.doAutoInstall();
659 if (_error
->PendingError() == true)
664 /* If we are in the Broken fixing mode we do not attempt to fix the
665 problems. This is if the user invoked install without -f and gave
667 if (BrokenFix
== true && Cache
->BrokenCount() != 0)
669 c1out
<< _("You might want to run 'apt-get -f install' to correct these:") << std::endl
;
670 ShowBroken(c1out
,Cache
,false);
671 return _error
->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
676 // Call the scored problem resolver
680 // Now we check the state of the packages,
681 if (Cache
->BrokenCount() != 0)
684 _("Some packages could not be installed. This may mean that you have\n"
685 "requested an impossible situation or if you are using the unstable\n"
686 "distribution that some required packages have not yet been created\n"
687 "or been moved out of Incoming.") << std::endl
;
693 _("Since you only requested a single operation it is extremely likely that\n"
694 "the package is simply not installable and a bug report against\n"
695 "that package should be filed.") << std::endl;
699 c1out
<< _("The following information may help to resolve the situation:") << std::endl
;
701 ShowBroken(c1out
,Cache
,false);
702 if (_error
->PendingError() == true)
705 return _error
->Error(_("Broken packages"));
708 if (!DoAutomaticRemove(Cache
))
711 // if nothing changed in the cache, but only the automark information
712 // we write the StateFile here, otherwise it will be written in
714 if (InstallAction
.AutoMarkChanged
> 0 &&
715 Cache
->DelCount() == 0 && Cache
->InstCount() == 0 &&
716 Cache
->BadCount() == 0 &&
717 _config
->FindB("APT::Get::Simulate",false) == false)
718 Cache
->writeStateFile(NULL
);
724 // DoInstall - Install packages from the command line /*{{{*/
725 // ---------------------------------------------------------------------
726 /* Install named packages */
727 bool DoInstall(CommandLine
&CmdL
)
730 if (Cache
.OpenForInstall() == false ||
731 Cache
.CheckDeps(CmdL
.FileSize() != 1) == false)
734 std::map
<unsigned short, APT::VersionSet
> verset
;
736 if(!DoCacheManipulationFromCommandLine(CmdL
, Cache
, verset
))
739 /* Print out a list of packages that are going to be installed extra
740 to what the user asked */
741 if (Cache
->InstCount() != verset
[MOD_INSTALL
].size())
744 std::string VersionsList
;
745 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
747 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
748 if ((*Cache
)[I
].Install() == false)
750 pkgCache::VerIterator Cand
= Cache
[I
].CandidateVerIter(Cache
);
752 if (verset
[MOD_INSTALL
].find(Cand
) != verset
[MOD_INSTALL
].end())
755 List
+= I
.FullName(true) + " ";
756 VersionsList
+= std::string(Cache
[I
].CandVersion
) + "\n";
759 ShowList(c1out
,_("The following extra packages will be installed:"),List
,VersionsList
);
762 /* Print out a list of suggested and recommended packages */
764 std::string SuggestsList
, RecommendsList
;
765 std::string SuggestsVersions
, RecommendsVersions
;
766 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
768 pkgCache::PkgIterator
Pkg(Cache
,Cache
.List
[J
]);
770 /* Just look at the ones we want to install */
771 if ((*Cache
)[Pkg
].Install() == false)
774 // get the recommends/suggests for the candidate ver
775 pkgCache::VerIterator CV
= (*Cache
)[Pkg
].CandidateVerIter(*Cache
);
776 for (pkgCache::DepIterator D
= CV
.DependsList(); D
.end() == false; )
778 pkgCache::DepIterator Start
;
779 pkgCache::DepIterator End
;
780 D
.GlobOr(Start
,End
); // advances D
782 // FIXME: we really should display a or-group as a or-group to the user
783 // the problem is that ShowList is incapable of doing this
784 std::string RecommendsOrList
,RecommendsOrVersions
;
785 std::string SuggestsOrList
,SuggestsOrVersions
;
786 bool foundInstalledInOrGroup
= false;
789 /* Skip if package is installed already, or is about to be */
790 std::string target
= Start
.TargetPkg().FullName(true) + " ";
791 pkgCache::PkgIterator
const TarPkg
= Start
.TargetPkg();
792 if (TarPkg
->SelectedState
== pkgCache::State::Install
||
793 TarPkg
->SelectedState
== pkgCache::State::Hold
||
794 Cache
[Start
.TargetPkg()].Install())
796 foundInstalledInOrGroup
=true;
800 /* Skip if we already saw it */
801 if (int(SuggestsList
.find(target
)) != -1 || int(RecommendsList
.find(target
)) != -1)
803 foundInstalledInOrGroup
=true;
807 // this is a dep on a virtual pkg, check if any package that provides it
808 // should be installed
809 if(Start
.TargetPkg().ProvidesList() != 0)
811 pkgCache::PrvIterator I
= Start
.TargetPkg().ProvidesList();
812 for (; I
.end() == false; ++I
)
814 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
815 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer() &&
816 Pkg
.CurrentVer() != 0)
817 foundInstalledInOrGroup
=true;
821 if (Start
->Type
== pkgCache::Dep::Suggests
)
823 SuggestsOrList
+= target
;
824 SuggestsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
827 if (Start
->Type
== pkgCache::Dep::Recommends
)
829 RecommendsOrList
+= target
;
830 RecommendsOrVersions
+= std::string(Cache
[Start
.TargetPkg()].CandVersion
) + "\n";
838 if(foundInstalledInOrGroup
== false)
840 RecommendsList
+= RecommendsOrList
;
841 RecommendsVersions
+= RecommendsOrVersions
;
842 SuggestsList
+= SuggestsOrList
;
843 SuggestsVersions
+= SuggestsOrVersions
;
849 ShowList(c1out
,_("Suggested packages:"),SuggestsList
,SuggestsVersions
);
850 ShowList(c1out
,_("Recommended packages:"),RecommendsList
,RecommendsVersions
);
854 // See if we need to prompt
855 // FIXME: check if really the packages in the set are going to be installed
856 if (Cache
->InstCount() == verset
[MOD_INSTALL
].size() && Cache
->DelCount() == 0)
857 return InstallPackages(Cache
,false,false);
859 return InstallPackages(Cache
,false);