Merge pull request #3 from cbaines/debian/sid
[ntk/apt.git] / apt-private / private-install.cc
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>
26
27 #include <set>
28 #include <locale.h>
29 #include <langinfo.h>
30 #include <fstream>
31 #include <termios.h>
32 #include <sys/ioctl.h>
33 #include <sys/stat.h>
34 #include <sys/statfs.h>
35 #include <sys/statvfs.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #include <regex.h>
41 #include <sys/wait.h>
42 #include <sstream>
43
44 #include "private-install.h"
45 #include "private-cachefile.h"
46 #include "private-output.h"
47 #include "private-cacheset.h"
48 #include "acqprogress.h"
49
50 #include <apti18n.h>
51 /*}}}*/
52
53 // CheckAuth - check if each download comes form a trusted source /*{{{*/
54 // ---------------------------------------------------------------------
55 /* */
56 static bool CheckAuth(pkgAcquire& Fetcher)
57 {
58 std::string UntrustedList;
59 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
60 {
61 if (!(*I)->IsTrusted())
62 {
63 UntrustedList += std::string((*I)->ShortDesc()) + " ";
64 }
65 }
66
67 if (UntrustedList == "")
68 {
69 return true;
70 }
71
72 ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
73
74 if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
75 {
76 c2out << _("Authentication warning overridden.\n");
77 return true;
78 }
79
80 if (_config->FindI("quiet",0) < 2
81 && _config->FindB("APT::Get::Assume-Yes",false) == false)
82 {
83 c2out << _("Install these packages without verification?") << std::flush;
84 if (!YnPrompt(false))
85 return _error->Error(_("Some packages could not be authenticated"));
86
87 return true;
88 }
89 else if (_config->FindB("APT::Get::Force-Yes",false) == true)
90 {
91 return true;
92 }
93
94 return _error->Error(_("There are problems and -y was used without --force-yes"));
95 }
96 /*}}}*/
97
98
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)
104 {
105 if (_config->FindB("APT::Get::Purge",false) == true)
106 {
107 pkgCache::PkgIterator I = Cache->PkgBegin();
108 for (; I.end() == false; ++I)
109 {
110 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
111 Cache->MarkDelete(I,true);
112 }
113 }
114
115 bool Fail = false;
116 bool Essential = false;
117
118 // Show all the various warning indicators
119 ShowDel(c1out,Cache);
120 ShowNew(c1out,Cache);
121 if (ShwKept == true)
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);
129 Fail |= Essential;
130 Stats(c1out,Cache);
131
132 // Sanity check
133 if (Cache->BrokenCount() != 0)
134 {
135 ShowBroken(c1out,Cache,false);
136 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
137 }
138
139 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
140 Cache->BadCount() == 0)
141 return true;
142
143 // No remove flag
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."));
146
147 // Run the simulator ..
148 if (_config->FindB("APT::Get::Simulate") == true)
149 {
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)
154 return false;
155 if (Res != pkgPackageManager::Completed)
156 return _error->Error(_("Internal error, Ordering didn't finish"));
157 return true;
158 }
159
160 // Create the text record parser
161 pkgRecords Recs(Cache);
162 if (_error->PendingError() == true)
163 return false;
164
165 // Create the download object
166 pkgAcquire Fetcher;
167 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
168 if (_config->FindB("APT::Get::Print-URIs", false) == true)
169 {
170 // force a hashsum for compatibility reasons
171 _config->CndSet("Acquire::ForceHash", "md5sum");
172 }
173 else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
174 return false;
175
176 // Read the source list
177 if (Cache.BuildSourceList() == false)
178 return false;
179 pkgSourceList *List = Cache.GetSourceList();
180
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)
185 return false;
186
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())
192 {
193 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
194 c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << std::endl;
195 }
196
197 // Number of bytes
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());
208
209 // Size delta
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());
215 else
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());
220
221 if (_error->PendingError() == true)
222 return false;
223
224 /* Check for enough free space, but only if we are actually going to
225 download */
226 if (_config->FindB("APT::Get::Print-URIs") == false &&
227 _config->FindB("APT::Get::Download",true) == true)
228 {
229 struct statvfs Buf;
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"),
234 OutputDir.c_str());
235 else
236 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
237 OutputDir.c_str());
238 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
239 {
240 struct statfs Stat;
241 if (statfs(OutputDir.c_str(),&Stat) != 0
242 #if HAVE_STRUCT_STATFS_F_TYPE
243 || unsigned(Stat.f_type) != RAMFS_MAGIC
244 #endif
245 )
246 return _error->Error(_("You don't have enough free space in %s."),
247 OutputDir.c_str());
248 }
249 }
250
251 // Fail safe check
252 if (_config->FindI("quiet",0) >= 2 ||
253 _config->FindB("APT::Get::Assume-Yes",false) == true)
254 {
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"));
257 }
258
259 if (Essential == true && Safety == true)
260 {
261 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
262 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
263
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!");
267 ioprintf(c2out,
268 _("You are about to do something potentially harmful.\n"
269 "To continue type in the phrase '%s'\n"
270 " ?] "),Prompt);
271 c2out << std::flush;
272 if (AnalPrompt(Prompt) == false)
273 {
274 c2out << _("Abort.") << std::endl;
275 exit(1);
276 }
277 }
278 else
279 {
280 // Prompt to continue
281 if (Ask == true || Fail == true)
282 {
283 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
284 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
285
286 if (_config->FindI("quiet",0) < 2 &&
287 _config->FindB("APT::Get::Assume-Yes",false) == false)
288 {
289 c2out << _("Do you want to continue?") << std::flush;
290 if (YnPrompt() == false)
291 {
292 c2out << _("Abort.") << std::endl;
293 exit(1);
294 }
295 }
296 }
297 }
298
299 // Just print out the uris an exit if the --print-uris flag was used
300 if (_config->FindB("APT::Get::Print-URIs") == true)
301 {
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;
306 return true;
307 }
308
309 if (!CheckAuth(Fetcher))
310 return false;
311
312 /* Unlock the dpkg lock if we are not going to be doing an install
313 after. */
314 if (_config->FindB("APT::Get::Download-Only",false) == true)
315 _system->UnLock();
316
317 // Run it
318 while (1)
319 {
320 bool Transient = false;
321 if (_config->FindB("APT::Get::Download",true) == false)
322 {
323 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
324 {
325 if ((*I)->Local == true)
326 {
327 ++I;
328 continue;
329 }
330
331 // Close the item and check if it was found in cache
332 (*I)->Finished();
333 if ((*I)->Complete == false)
334 Transient = true;
335
336 // Clear it out of the fetch list
337 delete *I;
338 I = Fetcher.ItemsBegin();
339 }
340 }
341
342 if (Fetcher.Run() == pkgAcquire::Failed)
343 return false;
344
345 // Print out errors
346 bool Failed = false;
347 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
348 {
349 if ((*I)->Status == pkgAcquire::Item::StatDone &&
350 (*I)->Complete == true)
351 continue;
352
353 if ((*I)->Status == pkgAcquire::Item::StatIdle)
354 {
355 Transient = true;
356 // Failed = true;
357 continue;
358 }
359
360 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
361 (*I)->ErrorText.c_str());
362 Failed = true;
363 }
364
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)
370 {
371 Transient = false;
372 Failed = true;
373 }
374
375 if (_config->FindB("APT::Get::Download-Only",false) == true)
376 {
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;
380 return true;
381 }
382
383 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
384 {
385 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
386 }
387
388 if (Transient == true && Failed == true)
389 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
390
391 // Try to deal with missing package files
392 if (Failed == true && PM->FixMissing() == false)
393 {
394 c2out << _("Unable to correct missing packages.") << std::endl;
395 return _error->Error(_("Aborting install."));
396 }
397
398 _system->UnLock();
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)
402 return false;
403 if (Res == pkgPackageManager::Completed)
404 break;
405
406 // Reload the fetcher object and loop again for media swapping
407 Fetcher.Shutdown();
408 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
409 return false;
410
411 _system->Lock();
412 }
413
414 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
415 if (disappearedPkgs.empty() == true)
416 return true;
417
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(" ");
422
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;
428
429 return true;
430 }
431 /*}}}*/
432
433
434 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
435 // ---------------------------------------------------------------------
436 /* Remove unused automatic packages */
437 bool DoAutomaticRemove(CacheFile &Cache)
438 {
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");
442
443 pkgDepCache::ActionGroup group(*Cache);
444 if(Debug)
445 std::cout << "DoAutomaticRemove()" << std::endl;
446
447 if (doAutoRemove == true &&
448 _config->FindB("APT::Get::Remove",true) == false)
449 {
450 c1out << _("We are not supposed to delete stuff, can't start "
451 "AutoRemover") << std::endl;
452 return false;
453 }
454
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);
458
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)
464 {
465 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
466 if (Cache[Pkg].Garbage)
467 {
468 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
469 if(Debug)
470 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
471
472 if (doAutoRemove)
473 {
474 if(Pkg.CurrentVer() != 0 &&
475 Pkg->CurrentState != pkgCache::State::ConfigFiles)
476 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
477 else
478 Cache->MarkKeep(Pkg, false, false);
479 }
480 else
481 {
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)
487 {
488 if (Pkg.CandVersion() != 0)
489 tooMuch.insert(Pkg);
490 Cache->MarkDelete(Pkg, false, 0, false);
491 }
492 // only show stuff in the list that is not yet marked for removal
493 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
494 ++autoRemoveCount;
495 }
496 }
497 }
498
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))
502 {
503 bool Changed;
504 do {
505 Changed = false;
506 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
507 Pkg != tooMuch.end() && Changed == false; ++Pkg)
508 {
509 APT::PackageSet too;
510 too.insert(*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)
518 {
519 if (R.IsNegative() == true ||
520 Cache->IsImportantDep(R) == false)
521 continue;
522 pkgCache::PkgIterator N = R.ParentPkg();
523 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
524 continue;
525 if (Debug == true)
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)
529 ++autoRemoveCount;
530 tooMuch.erase(Pkg);
531 Changed = true;
532 break;
533 }
534 }
535 }
536 } while (Changed == true);
537 }
538
539 std::string autoremovelist, autoremoveversions;
540 if (smallList == false && autoRemoveCount != 0)
541 {
542 for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg)
543 {
544 if (Cache[Pkg].Garbage == false)
545 continue;
546 autoremovelist += Pkg.FullName(true) + " ";
547 autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n";
548 }
549 }
550
551 // Now see if we had destroyed anything (if we had done anything)
552 if (Cache->BrokenCount() != 0)
553 {
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;
556 c1out << std::endl;
557 c1out << _("The following information may help to resolve the situation:") << std::endl;
558 c1out << std::endl;
559 ShowBroken(c1out,Cache,false);
560
561 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
562 }
563
564 // if we don't remove them, we should show them!
565 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
566 {
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);
571 else
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;
575 }
576 return true;
577 }
578 /*}}}*/
579
580
581
582
583 // DoInstall - Install packages from the command line /*{{{*/
584 // ---------------------------------------------------------------------
585 /* Install named packages */
586 bool DoInstall(CommandLine &CmdL)
587 {
588 CacheFile Cache;
589 if (Cache.OpenForInstall() == false ||
590 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
591 return false;
592
593 // Enter the special broken fixing mode if the user specified arguments
594 bool BrokenFix = false;
595 if (Cache->BrokenCount() != 0)
596 BrokenFix = true;
597
598 pkgProblemResolver* Fix = NULL;
599 if (_config->FindB("APT::Get::CallResolver", true) == true)
600 Fix = new pkgProblemResolver(Cache);
601
602 static const unsigned short MOD_REMOVE = 1;
603 static const unsigned short MOD_INSTALL = 2;
604
605 unsigned short fallback = MOD_INSTALL;
606 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
607 fallback = MOD_REMOVE;
608 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
609 {
610 _config->Set("APT::Get::Purge", true);
611 fallback = MOD_REMOVE;
612 }
613 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
614 {
615 _config->Set("APT::Get::AutomaticRemove", "true");
616 fallback = MOD_REMOVE;
617 }
618
619 std::list<APT::VersionSet::Modifier> mods;
620 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
621 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
622 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
623 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
624 CacheSetHelperAPTGet helper(c0out);
625 std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
626 CmdL.FileList + 1, mods, fallback, helper);
627
628 if (_error->PendingError() == true)
629 {
630 helper.showVirtualPackageErrors(Cache);
631 if (Fix != NULL)
632 delete Fix;
633 return false;
634 }
635
636
637 TryToInstall InstallAction(Cache, Fix, BrokenFix);
638 TryToRemove RemoveAction(Cache, Fix);
639
640 // new scope for the ActionGroup
641 {
642 pkgDepCache::ActionGroup group(Cache);
643 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
644
645 for (unsigned short i = 0; order[i] != 0; ++i)
646 {
647 if (order[i] == MOD_INSTALL)
648 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
649 else if (order[i] == MOD_REMOVE)
650 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
651 }
652
653 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
654 {
655 for (unsigned short i = 0; order[i] != 0; ++i)
656 {
657 if (order[i] != MOD_INSTALL)
658 continue;
659 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
660 InstallAction.doAutoInstall();
661 }
662 }
663
664 if (_error->PendingError() == true)
665 {
666 if (Fix != NULL)
667 delete Fix;
668 return false;
669 }
670
671 /* If we are in the Broken fixing mode we do not attempt to fix the
672 problems. This is if the user invoked install without -f and gave
673 packages */
674 if (BrokenFix == true && Cache->BrokenCount() != 0)
675 {
676 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
677 ShowBroken(c1out,Cache,false);
678 if (Fix != NULL)
679 delete Fix;
680 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
681 }
682
683 if (Fix != NULL)
684 {
685 // Call the scored problem resolver
686 Fix->Resolve(true);
687 delete Fix;
688 }
689
690 // Now we check the state of the packages,
691 if (Cache->BrokenCount() != 0)
692 {
693 c1out <<
694 _("Some packages could not be installed. This may mean that you have\n"
695 "requested an impossible situation or if you are using the unstable\n"
696 "distribution that some required packages have not yet been created\n"
697 "or been moved out of Incoming.") << std::endl;
698 /*
699 if (Packages == 1)
700 {
701 c1out << std::endl;
702 c1out <<
703 _("Since you only requested a single operation it is extremely likely that\n"
704 "the package is simply not installable and a bug report against\n"
705 "that package should be filed.") << std::endl;
706 }
707 */
708
709 c1out << _("The following information may help to resolve the situation:") << std::endl;
710 c1out << std::endl;
711 ShowBroken(c1out,Cache,false);
712 if (_error->PendingError() == true)
713 return false;
714 else
715 return _error->Error(_("Broken packages"));
716 }
717 }
718 if (!DoAutomaticRemove(Cache))
719 return false;
720
721 /* Print out a list of packages that are going to be installed extra
722 to what the user asked */
723 if (Cache->InstCount() != verset[MOD_INSTALL].size())
724 {
725 std::string List;
726 std::string VersionsList;
727 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
728 {
729 pkgCache::PkgIterator I(Cache,Cache.List[J]);
730 if ((*Cache)[I].Install() == false)
731 continue;
732 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
733
734 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
735 continue;
736
737 List += I.FullName(true) + " ";
738 VersionsList += std::string(Cache[I].CandVersion) + "\n";
739 }
740
741 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
742 }
743
744 /* Print out a list of suggested and recommended packages */
745 {
746 std::string SuggestsList, RecommendsList;
747 std::string SuggestsVersions, RecommendsVersions;
748 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
749 {
750 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
751
752 /* Just look at the ones we want to install */
753 if ((*Cache)[Pkg].Install() == false)
754 continue;
755
756 // get the recommends/suggests for the candidate ver
757 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
758 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
759 {
760 pkgCache::DepIterator Start;
761 pkgCache::DepIterator End;
762 D.GlobOr(Start,End); // advances D
763
764 // FIXME: we really should display a or-group as a or-group to the user
765 // the problem is that ShowList is incapable of doing this
766 std::string RecommendsOrList,RecommendsOrVersions;
767 std::string SuggestsOrList,SuggestsOrVersions;
768 bool foundInstalledInOrGroup = false;
769 for(;;)
770 {
771 /* Skip if package is installed already, or is about to be */
772 std::string target = Start.TargetPkg().FullName(true) + " ";
773 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
774 if (TarPkg->SelectedState == pkgCache::State::Install ||
775 TarPkg->SelectedState == pkgCache::State::Hold ||
776 Cache[Start.TargetPkg()].Install())
777 {
778 foundInstalledInOrGroup=true;
779 break;
780 }
781
782 /* Skip if we already saw it */
783 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
784 {
785 foundInstalledInOrGroup=true;
786 break;
787 }
788
789 // this is a dep on a virtual pkg, check if any package that provides it
790 // should be installed
791 if(Start.TargetPkg().ProvidesList() != 0)
792 {
793 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
794 for (; I.end() == false; ++I)
795 {
796 pkgCache::PkgIterator Pkg = I.OwnerPkg();
797 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
798 Pkg.CurrentVer() != 0)
799 foundInstalledInOrGroup=true;
800 }
801 }
802
803 if (Start->Type == pkgCache::Dep::Suggests)
804 {
805 SuggestsOrList += target;
806 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
807 }
808
809 if (Start->Type == pkgCache::Dep::Recommends)
810 {
811 RecommendsOrList += target;
812 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
813 }
814
815 if (Start >= End)
816 break;
817 ++Start;
818 }
819
820 if(foundInstalledInOrGroup == false)
821 {
822 RecommendsList += RecommendsOrList;
823 RecommendsVersions += RecommendsOrVersions;
824 SuggestsList += SuggestsOrList;
825 SuggestsVersions += SuggestsOrVersions;
826 }
827
828 }
829 }
830
831 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
832 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
833
834 }
835
836 // if nothing changed in the cache, but only the automark information
837 // we write the StateFile here, otherwise it will be written in
838 // cache.commit()
839 if (InstallAction.AutoMarkChanged > 0 &&
840 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
841 Cache->BadCount() == 0 &&
842 _config->FindB("APT::Get::Simulate",false) == false)
843 Cache->writeStateFile(NULL);
844
845 // See if we need to prompt
846 // FIXME: check if really the packages in the set are going to be installed
847 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
848 return InstallPackages(Cache,false,false);
849
850 return InstallPackages(Cache,false);
851 }
852 /*}}}*/