rename APT::Progress::Packagemanager Started->Start, Finished->Stop to match pkgAcqui...
[ntk/apt.git] / apt-private / private-install.cc
CommitLineData
b9179170
MV
1// Include Files /*{{{*/
2#include <config.h>
3
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>
e6ad8031 26#include <apt-pkg/iprogress.h>
b9179170
MV
27
28#include <set>
29#include <locale.h>
30#include <langinfo.h>
31#include <fstream>
32#include <termios.h>
33#include <sys/ioctl.h>
34#include <sys/stat.h>
35#include <sys/statfs.h>
36#include <sys/statvfs.h>
37#include <signal.h>
38#include <unistd.h>
39#include <stdio.h>
40#include <errno.h>
41#include <regex.h>
42#include <sys/wait.h>
43#include <sstream>
44
45#include "private-install.h"
866893a6 46#include "private-download.h"
b9179170
MV
47#include "private-cachefile.h"
48#include "private-output.h"
49#include "private-cacheset.h"
50#include "acqprogress.h"
51
52#include <apti18n.h>
53 /*}}}*/
54
b9179170
MV
55// InstallPackages - Actually download and install the packages /*{{{*/
56// ---------------------------------------------------------------------
57/* This displays the informative messages describing what is going to
58 happen and then calls the download routines */
59bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
60{
61 if (_config->FindB("APT::Get::Purge",false) == true)
62 {
63 pkgCache::PkgIterator I = Cache->PkgBegin();
64 for (; I.end() == false; ++I)
65 {
66 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
67 Cache->MarkDelete(I,true);
68 }
69 }
70
71 bool Fail = false;
72 bool Essential = false;
73
74 // Show all the various warning indicators
75 ShowDel(c1out,Cache);
76 ShowNew(c1out,Cache);
77 if (ShwKept == true)
78 ShowKept(c1out,Cache);
79 Fail |= !ShowHold(c1out,Cache);
80 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
81 ShowUpgraded(c1out,Cache);
82 Fail |= !ShowDowngraded(c1out,Cache);
83 if (_config->FindB("APT::Get::Download-Only",false) == false)
84 Essential = !ShowEssential(c1out,Cache);
85 Fail |= Essential;
86 Stats(c1out,Cache);
87
88 // Sanity check
89 if (Cache->BrokenCount() != 0)
90 {
91 ShowBroken(c1out,Cache,false);
92 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
93 }
94
95 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
96 Cache->BadCount() == 0)
97 return true;
98
99 // No remove flag
100 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
101 return _error->Error(_("Packages need to be removed but remove is disabled."));
102
103 // Run the simulator ..
104 if (_config->FindB("APT::Get::Simulate") == true)
105 {
106 pkgSimulate PM(Cache);
107 int status_fd = _config->FindI("APT::Status-Fd",-1);
e6ad8031
MV
108 APT::Progress::PackageManager *progress = NULL;
109 if (status_fd > 0)
110 progress = new APT::Progress::PackageManagerProgressFd(status_fd);
111 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
112 delete progress;
b9179170
MV
113 if (Res == pkgPackageManager::Failed)
114 return false;
115 if (Res != pkgPackageManager::Completed)
116 return _error->Error(_("Internal error, Ordering didn't finish"));
117 return true;
118 }
119
120 // Create the text record parser
121 pkgRecords Recs(Cache);
122 if (_error->PendingError() == true)
123 return false;
124
125 // Create the download object
126 pkgAcquire Fetcher;
127 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
128 if (_config->FindB("APT::Get::Print-URIs", false) == true)
129 {
130 // force a hashsum for compatibility reasons
131 _config->CndSet("Acquire::ForceHash", "md5sum");
132 }
133 else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
134 return false;
135
136 // Read the source list
137 if (Cache.BuildSourceList() == false)
138 return false;
139 pkgSourceList *List = Cache.GetSourceList();
140
141 // Create the package manager and prepare to download
142 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
143 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
144 _error->PendingError() == true)
145 return false;
146
147 // Display statistics
148 unsigned long long FetchBytes = Fetcher.FetchNeeded();
149 unsigned long long FetchPBytes = Fetcher.PartialPresent();
150 unsigned long long DebBytes = Fetcher.TotalNeeded();
151 if (DebBytes != Cache->DebSize())
152 {
153 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
154 c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl;
155 }
156
157 // Number of bytes
158 if (DebBytes != FetchBytes)
159 //TRANSLATOR: The required space between number and unit is already included
160 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
161 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
162 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
163 else if (DebBytes != 0)
164 //TRANSLATOR: The required space between number and unit is already included
165 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
166 ioprintf(c1out,_("Need to get %sB of archives.\n"),
167 SizeToStr(DebBytes).c_str());
168
169 // Size delta
170 if (Cache->UsrSize() >= 0)
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 of additional disk space will be used.\n"),
174 SizeToStr(Cache->UsrSize()).c_str());
175 else
176 //TRANSLATOR: The required space between number and unit is already included
177 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
178 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
179 SizeToStr(-1*Cache->UsrSize()).c_str());
180
181 if (_error->PendingError() == true)
182 return false;
183
184 /* Check for enough free space, but only if we are actually going to
185 download */
186 if (_config->FindB("APT::Get::Print-URIs") == false &&
187 _config->FindB("APT::Get::Download",true) == true)
188 {
189 struct statvfs Buf;
190 std::string OutputDir = _config->FindDir("Dir::Cache::Archives");
191 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
192 if (errno == EOVERFLOW)
193 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
194 OutputDir.c_str());
195 else
196 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
197 OutputDir.c_str());
198 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
199 {
200 struct statfs Stat;
201 if (statfs(OutputDir.c_str(),&Stat) != 0
202#if HAVE_STRUCT_STATFS_F_TYPE
203 || unsigned(Stat.f_type) != RAMFS_MAGIC
204#endif
205 )
206 return _error->Error(_("You don't have enough free space in %s."),
207 OutputDir.c_str());
208 }
209 }
210
211 // Fail safe check
212 if (_config->FindI("quiet",0) >= 2 ||
213 _config->FindB("APT::Get::Assume-Yes",false) == true)
214 {
215 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
216 return _error->Error(_("There are problems and -y was used without --force-yes"));
217 }
218
219 if (Essential == true && Safety == true)
220 {
221 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
222 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
223
224 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
225 // careful with hard to type or special characters (like non-breaking spaces)
226 const char *Prompt = _("Yes, do as I say!");
227 ioprintf(c2out,
228 _("You are about to do something potentially harmful.\n"
229 "To continue type in the phrase '%s'\n"
230 " ?] "),Prompt);
231 c2out << std::flush;
232 if (AnalPrompt(Prompt) == false)
233 {
234 c2out << _("Abort.") << std::endl;
235 exit(1);
236 }
237 }
238 else
239 {
240 // Prompt to continue
241 if (Ask == true || Fail == true)
242 {
243 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
244 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
245
246 if (_config->FindI("quiet",0) < 2 &&
247 _config->FindB("APT::Get::Assume-Yes",false) == false)
248 {
249 c2out << _("Do you want to continue?") << std::flush;
250 if (YnPrompt() == false)
251 {
252 c2out << _("Abort.") << std::endl;
253 exit(1);
254 }
255 }
256 }
257 }
258
259 // Just print out the uris an exit if the --print-uris flag was used
260 if (_config->FindB("APT::Get::Print-URIs") == true)
261 {
262 pkgAcquire::UriIterator I = Fetcher.UriBegin();
263 for (; I != Fetcher.UriEnd(); ++I)
ac69a4d8 264 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
b9179170
MV
265 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
266 return true;
267 }
268
866893a6 269 if (!CheckAuth(Fetcher, true))
b9179170
MV
270 return false;
271
272 /* Unlock the dpkg lock if we are not going to be doing an install
273 after. */
274 if (_config->FindB("APT::Get::Download-Only",false) == true)
275 _system->UnLock();
276
277 // Run it
278 while (1)
279 {
280 bool Transient = false;
281 if (_config->FindB("APT::Get::Download",true) == false)
282 {
283 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
284 {
285 if ((*I)->Local == true)
286 {
287 ++I;
288 continue;
289 }
290
291 // Close the item and check if it was found in cache
292 (*I)->Finished();
293 if ((*I)->Complete == false)
294 Transient = true;
295
296 // Clear it out of the fetch list
297 delete *I;
298 I = Fetcher.ItemsBegin();
299 }
300 }
b9179170 301
866893a6
DK
302 bool Failed = false;
303 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
304 return false;
b9179170
MV
305
306 /* If we are in no download mode and missing files and there were
307 'failures' then the user must specify -m. Furthermore, there
308 is no such thing as a transient error in no-download mode! */
309 if (Transient == true &&
310 _config->FindB("APT::Get::Download",true) == false)
311 {
312 Transient = false;
313 Failed = true;
314 }
315
316 if (_config->FindB("APT::Get::Download-Only",false) == true)
317 {
318 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
319 return _error->Error(_("Some files failed to download"));
320 c1out << _("Download complete and in download only mode") << std::endl;
321 return true;
322 }
323
324 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
325 {
326 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
327 }
328
329 if (Transient == true && Failed == true)
330 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
331
332 // Try to deal with missing package files
333 if (Failed == true && PM->FixMissing() == false)
334 {
335 c2out << _("Unable to correct missing packages.") << std::endl;
336 return _error->Error(_("Aborting install."));
337 }
338
339 _system->UnLock();
e6ad8031
MV
340
341 // FIXME: make this a factory
342 // select the right progress
b9179170 343 int status_fd = _config->FindI("APT::Status-Fd",-1);
e6ad8031
MV
344 APT::Progress::PackageManager *progress = NULL;
345 if (status_fd > 0)
346 progress = new APT::Progress::PackageManagerProgressFd(status_fd);
347 else if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
348 progress = new APT::Progress::PackageManagerFancy();
349 else if (_config->FindB("Dpkg::Progress",
350 _config->FindB("DpkgPM::Progress", false)) == true)
351 progress = new APT::Progress::PackageManagerText();
352 else
353 progress = new APT::Progress::PackageManager();
354 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
355 delete progress;
356
b9179170
MV
357 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
358 return false;
359 if (Res == pkgPackageManager::Completed)
360 break;
361
362 // Reload the fetcher object and loop again for media swapping
363 Fetcher.Shutdown();
364 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
365 return false;
366
367 _system->Lock();
368 }
369
370 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
371 if (disappearedPkgs.empty() == true)
372 return true;
373
374 std::string disappear;
375 for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
376 d != disappearedPkgs.end(); ++d)
377 disappear.append(*d).append(" ");
378
379 ShowList(c1out, P_("The following package disappeared from your system as\n"
380 "all files have been overwritten by other packages:",
381 "The following packages disappeared from your system as\n"
382 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
383 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
384
385 return true;
386}
387 /*}}}*/
b9179170
MV
388// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
389// ---------------------------------------------------------------------
390/* Remove unused automatic packages */
391bool DoAutomaticRemove(CacheFile &Cache)
392{
393 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
394 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
395 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
396
397 pkgDepCache::ActionGroup group(*Cache);
398 if(Debug)
399 std::cout << "DoAutomaticRemove()" << std::endl;
400
401 if (doAutoRemove == true &&
402 _config->FindB("APT::Get::Remove",true) == false)
403 {
404 c1out << _("We are not supposed to delete stuff, can't start "
405 "AutoRemover") << std::endl;
406 return false;
407 }
408
409 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
410 bool smallList = (hideAutoRemove == false &&
411 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
412
413 unsigned long autoRemoveCount = 0;
414 APT::PackageSet tooMuch;
415 APT::PackageList autoRemoveList;
416 // look over the cache to see what can be removed
417 for (unsigned J = 0; J < Cache->Head().PackageCount; ++J)
418 {
419 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
420 if (Cache[Pkg].Garbage)
421 {
422 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
423 if(Debug)
424 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
425
426 if (doAutoRemove)
427 {
428 if(Pkg.CurrentVer() != 0 &&
429 Pkg->CurrentState != pkgCache::State::ConfigFiles)
430 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
431 else
432 Cache->MarkKeep(Pkg, false, false);
433 }
434 else
435 {
436 if (hideAutoRemove == false && Cache[Pkg].Delete() == false)
437 autoRemoveList.insert(Pkg);
438 // if the package is a new install and already garbage we don't need to
439 // install it in the first place, so nuke it instead of show it
440 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
441 {
442 if (Pkg.CandVersion() != 0)
443 tooMuch.insert(Pkg);
444 Cache->MarkDelete(Pkg, false, 0, false);
445 }
446 // only show stuff in the list that is not yet marked for removal
447 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
448 ++autoRemoveCount;
449 }
450 }
451 }
452
453 // we could have removed a new dependency of a garbage package,
454 // so check if a reverse depends is broken and if so install it again.
455 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
456 {
457 bool Changed;
458 do {
459 Changed = false;
460 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
3a7a206f 461 Pkg != tooMuch.end(); ++Pkg)
b9179170
MV
462 {
463 APT::PackageSet too;
464 too.insert(*Pkg);
465 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
466 Prv.end() == false; ++Prv)
467 too.insert(Prv.ParentPkg());
3a7a206f
DK
468 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
469 {
b9179170
MV
470 for (pkgCache::DepIterator R = P.RevDependsList();
471 R.end() == false; ++R)
472 {
473 if (R.IsNegative() == true ||
474 Cache->IsImportantDep(R) == false)
475 continue;
476 pkgCache::PkgIterator N = R.ParentPkg();
477 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
478 continue;
479 if (Debug == true)
480 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
481 Cache->MarkInstall(Pkg, false, 0, false);
482 if (hideAutoRemove == false)
483 ++autoRemoveCount;
484 tooMuch.erase(Pkg);
485 Changed = true;
486 break;
487 }
3a7a206f
DK
488 if (Changed == true)
489 break;
b9179170 490 }
3a7a206f
DK
491 if (Changed == true)
492 break;
b9179170
MV
493 }
494 } while (Changed == true);
495 }
496
497 std::string autoremovelist, autoremoveversions;
498 if (smallList == false && autoRemoveCount != 0)
499 {
500 for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg)
501 {
502 if (Cache[Pkg].Garbage == false)
503 continue;
504 autoremovelist += Pkg.FullName(true) + " ";
505 autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n";
506 }
507 }
508
509 // Now see if we had destroyed anything (if we had done anything)
510 if (Cache->BrokenCount() != 0)
511 {
512 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
513 "shouldn't happen. Please file a bug report against apt.") << std::endl;
514 c1out << std::endl;
515 c1out << _("The following information may help to resolve the situation:") << std::endl;
516 c1out << std::endl;
517 ShowBroken(c1out,Cache,false);
518
519 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
520 }
521
522 // if we don't remove them, we should show them!
523 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
524 {
525 if (smallList == false)
526 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
527 "The following packages were automatically installed and are no longer required:",
528 autoRemoveCount), autoremovelist, autoremoveversions);
529 else
530 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
531 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
532 c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl;
533 }
534 return true;
535}
536 /*}}}*/
ee0167c4 537// DoCacheManipulationFromCommandLine /*{{{*/
d8a8f9d7
MV
538static const unsigned short MOD_REMOVE = 1;
539static const unsigned short MOD_INSTALL = 2;
b9179170 540
d8a8f9d7
MV
541bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
542{
543 std::map<unsigned short, APT::VersionSet> verset;
544 return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
545}
d8a8f9d7
MV
546bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
547 std::map<unsigned short, APT::VersionSet> &verset)
b9179170 548{
d8a8f9d7 549
b9179170
MV
550 // Enter the special broken fixing mode if the user specified arguments
551 bool BrokenFix = false;
552 if (Cache->BrokenCount() != 0)
553 BrokenFix = true;
554
be0270de 555 SPtr<pkgProblemResolver> Fix;
b9179170
MV
556 if (_config->FindB("APT::Get::CallResolver", true) == true)
557 Fix = new pkgProblemResolver(Cache);
558
b9179170
MV
559 unsigned short fallback = MOD_INSTALL;
560 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
561 fallback = MOD_REMOVE;
562 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
563 {
564 _config->Set("APT::Get::Purge", true);
565 fallback = MOD_REMOVE;
566 }
567 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
568 {
569 _config->Set("APT::Get::AutomaticRemove", "true");
570 fallback = MOD_REMOVE;
571 }
572
573 std::list<APT::VersionSet::Modifier> mods;
574 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
575 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
576 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
577 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
578 CacheSetHelperAPTGet helper(c0out);
d8a8f9d7 579 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
b9179170
MV
580 CmdL.FileList + 1, mods, fallback, helper);
581
582 if (_error->PendingError() == true)
583 {
584 helper.showVirtualPackageErrors(Cache);
b9179170
MV
585 return false;
586 }
587
588
589 TryToInstall InstallAction(Cache, Fix, BrokenFix);
590 TryToRemove RemoveAction(Cache, Fix);
591
592 // new scope for the ActionGroup
593 {
594 pkgDepCache::ActionGroup group(Cache);
595 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
596
597 for (unsigned short i = 0; order[i] != 0; ++i)
598 {
599 if (order[i] == MOD_INSTALL)
600 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
601 else if (order[i] == MOD_REMOVE)
602 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
603 }
604
605 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
606 {
607 for (unsigned short i = 0; order[i] != 0; ++i)
608 {
609 if (order[i] != MOD_INSTALL)
610 continue;
611 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
612 InstallAction.doAutoInstall();
613 }
614 }
615
616 if (_error->PendingError() == true)
617 {
b9179170
MV
618 return false;
619 }
620
621 /* If we are in the Broken fixing mode we do not attempt to fix the
622 problems. This is if the user invoked install without -f and gave
623 packages */
624 if (BrokenFix == true && Cache->BrokenCount() != 0)
625 {
626 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
627 ShowBroken(c1out,Cache,false);
b9179170
MV
628 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
629 }
630
631 if (Fix != NULL)
632 {
633 // Call the scored problem resolver
634 Fix->Resolve(true);
b9179170
MV
635 }
636
637 // Now we check the state of the packages,
638 if (Cache->BrokenCount() != 0)
639 {
640 c1out <<
641 _("Some packages could not be installed. This may mean that you have\n"
642 "requested an impossible situation or if you are using the unstable\n"
643 "distribution that some required packages have not yet been created\n"
644 "or been moved out of Incoming.") << std::endl;
645 /*
646 if (Packages == 1)
647 {
648 c1out << std::endl;
649 c1out <<
650 _("Since you only requested a single operation it is extremely likely that\n"
651 "the package is simply not installable and a bug report against\n"
652 "that package should be filed.") << std::endl;
653 }
654 */
655
656 c1out << _("The following information may help to resolve the situation:") << std::endl;
657 c1out << std::endl;
658 ShowBroken(c1out,Cache,false);
659 if (_error->PendingError() == true)
660 return false;
661 else
662 return _error->Error(_("Broken packages"));
663 }
664 }
665 if (!DoAutomaticRemove(Cache))
666 return false;
667
d8a8f9d7
MV
668 // if nothing changed in the cache, but only the automark information
669 // we write the StateFile here, otherwise it will be written in
670 // cache.commit()
671 if (InstallAction.AutoMarkChanged > 0 &&
672 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
673 Cache->BadCount() == 0 &&
674 _config->FindB("APT::Get::Simulate",false) == false)
675 Cache->writeStateFile(NULL);
676
677 return true;
678}
ee0167c4 679 /*}}}*/
d8a8f9d7
MV
680// DoInstall - Install packages from the command line /*{{{*/
681// ---------------------------------------------------------------------
682/* Install named packages */
683bool DoInstall(CommandLine &CmdL)
684{
685 CacheFile Cache;
686 if (Cache.OpenForInstall() == false ||
687 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
688 return false;
689
690 std::map<unsigned short, APT::VersionSet> verset;
691
692 if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
693 return false;
694
b9179170
MV
695 /* Print out a list of packages that are going to be installed extra
696 to what the user asked */
697 if (Cache->InstCount() != verset[MOD_INSTALL].size())
698 {
699 std::string List;
700 std::string VersionsList;
701 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
702 {
703 pkgCache::PkgIterator I(Cache,Cache.List[J]);
704 if ((*Cache)[I].Install() == false)
705 continue;
706 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
707
708 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
709 continue;
710
711 List += I.FullName(true) + " ";
712 VersionsList += std::string(Cache[I].CandVersion) + "\n";
713 }
714
715 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
716 }
717
718 /* Print out a list of suggested and recommended packages */
719 {
720 std::string SuggestsList, RecommendsList;
721 std::string SuggestsVersions, RecommendsVersions;
722 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
723 {
724 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
725
726 /* Just look at the ones we want to install */
727 if ((*Cache)[Pkg].Install() == false)
728 continue;
729
730 // get the recommends/suggests for the candidate ver
731 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
732 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
733 {
734 pkgCache::DepIterator Start;
735 pkgCache::DepIterator End;
736 D.GlobOr(Start,End); // advances D
737
738 // FIXME: we really should display a or-group as a or-group to the user
739 // the problem is that ShowList is incapable of doing this
740 std::string RecommendsOrList,RecommendsOrVersions;
741 std::string SuggestsOrList,SuggestsOrVersions;
742 bool foundInstalledInOrGroup = false;
743 for(;;)
744 {
745 /* Skip if package is installed already, or is about to be */
746 std::string target = Start.TargetPkg().FullName(true) + " ";
747 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
748 if (TarPkg->SelectedState == pkgCache::State::Install ||
749 TarPkg->SelectedState == pkgCache::State::Hold ||
750 Cache[Start.TargetPkg()].Install())
751 {
752 foundInstalledInOrGroup=true;
753 break;
754 }
755
756 /* Skip if we already saw it */
757 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
758 {
759 foundInstalledInOrGroup=true;
760 break;
761 }
762
763 // this is a dep on a virtual pkg, check if any package that provides it
764 // should be installed
765 if(Start.TargetPkg().ProvidesList() != 0)
766 {
767 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
768 for (; I.end() == false; ++I)
769 {
770 pkgCache::PkgIterator Pkg = I.OwnerPkg();
771 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
772 Pkg.CurrentVer() != 0)
773 foundInstalledInOrGroup=true;
774 }
775 }
776
777 if (Start->Type == pkgCache::Dep::Suggests)
778 {
779 SuggestsOrList += target;
780 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
781 }
782
783 if (Start->Type == pkgCache::Dep::Recommends)
784 {
785 RecommendsOrList += target;
786 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
787 }
788
789 if (Start >= End)
790 break;
791 ++Start;
792 }
793
794 if(foundInstalledInOrGroup == false)
795 {
796 RecommendsList += RecommendsOrList;
797 RecommendsVersions += RecommendsOrVersions;
798 SuggestsList += SuggestsOrList;
799 SuggestsVersions += SuggestsOrVersions;
800 }
801
802 }
803 }
804
805 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
806 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
807
808 }
809
b9179170
MV
810 // See if we need to prompt
811 // FIXME: check if really the packages in the set are going to be installed
812 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
813 return InstallPackages(Cache,false,false);
814
815 return InstallPackages(Cache,false);
816}
817 /*}}}*/