]> git.saurik.com Git - apt.git/blob - apt-private/private-install.cc
Merge remote-tracking branch 'upstream/debian/sid' into feature/upgrade-with-new
[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 static const unsigned short MOD_REMOVE = 1;
581 static const unsigned short MOD_INSTALL = 2;
582
583 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
584 {
585 std::map<unsigned short, APT::VersionSet> verset;
586 return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
587 }
588
589 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
590 std::map<unsigned short, APT::VersionSet> &verset)
591 {
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 SPtr<pkgProblemResolver> Fix;
599 if (_config->FindB("APT::Get::CallResolver", true) == true)
600 Fix = new pkgProblemResolver(Cache);
601
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)
606 {
607 _config->Set("APT::Get::Purge", true);
608 fallback = MOD_REMOVE;
609 }
610 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
611 {
612 _config->Set("APT::Get::AutomaticRemove", "true");
613 fallback = MOD_REMOVE;
614 }
615
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);
624
625 if (_error->PendingError() == true)
626 {
627 helper.showVirtualPackageErrors(Cache);
628 return false;
629 }
630
631
632 TryToInstall InstallAction(Cache, Fix, BrokenFix);
633 TryToRemove RemoveAction(Cache, Fix);
634
635 // new scope for the ActionGroup
636 {
637 pkgDepCache::ActionGroup group(Cache);
638 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
639
640 for (unsigned short i = 0; order[i] != 0; ++i)
641 {
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);
646 }
647
648 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
649 {
650 for (unsigned short i = 0; order[i] != 0; ++i)
651 {
652 if (order[i] != MOD_INSTALL)
653 continue;
654 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
655 InstallAction.doAutoInstall();
656 }
657 }
658
659 if (_error->PendingError() == true)
660 {
661 return false;
662 }
663
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
666 packages */
667 if (BrokenFix == true && Cache->BrokenCount() != 0)
668 {
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)."));
672 }
673
674 if (Fix != NULL)
675 {
676 // Call the scored problem resolver
677 Fix->Resolve(true);
678 }
679
680 // Now we check the state of the packages,
681 if (Cache->BrokenCount() != 0)
682 {
683 c1out <<
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;
688 /*
689 if (Packages == 1)
690 {
691 c1out << std::endl;
692 c1out <<
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;
696 }
697 */
698
699 c1out << _("The following information may help to resolve the situation:") << std::endl;
700 c1out << std::endl;
701 ShowBroken(c1out,Cache,false);
702 if (_error->PendingError() == true)
703 return false;
704 else
705 return _error->Error(_("Broken packages"));
706 }
707 }
708 if (!DoAutomaticRemove(Cache))
709 return false;
710
711 // if nothing changed in the cache, but only the automark information
712 // we write the StateFile here, otherwise it will be written in
713 // cache.commit()
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);
719
720 return true;
721 }
722
723
724 // DoInstall - Install packages from the command line /*{{{*/
725 // ---------------------------------------------------------------------
726 /* Install named packages */
727 bool DoInstall(CommandLine &CmdL)
728 {
729 CacheFile Cache;
730 if (Cache.OpenForInstall() == false ||
731 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
732 return false;
733
734 std::map<unsigned short, APT::VersionSet> verset;
735
736 if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
737 return false;
738
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())
742 {
743 std::string List;
744 std::string VersionsList;
745 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
746 {
747 pkgCache::PkgIterator I(Cache,Cache.List[J]);
748 if ((*Cache)[I].Install() == false)
749 continue;
750 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
751
752 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
753 continue;
754
755 List += I.FullName(true) + " ";
756 VersionsList += std::string(Cache[I].CandVersion) + "\n";
757 }
758
759 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
760 }
761
762 /* Print out a list of suggested and recommended packages */
763 {
764 std::string SuggestsList, RecommendsList;
765 std::string SuggestsVersions, RecommendsVersions;
766 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
767 {
768 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
769
770 /* Just look at the ones we want to install */
771 if ((*Cache)[Pkg].Install() == false)
772 continue;
773
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; )
777 {
778 pkgCache::DepIterator Start;
779 pkgCache::DepIterator End;
780 D.GlobOr(Start,End); // advances D
781
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;
787 for(;;)
788 {
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())
795 {
796 foundInstalledInOrGroup=true;
797 break;
798 }
799
800 /* Skip if we already saw it */
801 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
802 {
803 foundInstalledInOrGroup=true;
804 break;
805 }
806
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)
810 {
811 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
812 for (; I.end() == false; ++I)
813 {
814 pkgCache::PkgIterator Pkg = I.OwnerPkg();
815 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
816 Pkg.CurrentVer() != 0)
817 foundInstalledInOrGroup=true;
818 }
819 }
820
821 if (Start->Type == pkgCache::Dep::Suggests)
822 {
823 SuggestsOrList += target;
824 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
825 }
826
827 if (Start->Type == pkgCache::Dep::Recommends)
828 {
829 RecommendsOrList += target;
830 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
831 }
832
833 if (Start >= End)
834 break;
835 ++Start;
836 }
837
838 if(foundInstalledInOrGroup == false)
839 {
840 RecommendsList += RecommendsOrList;
841 RecommendsVersions += RecommendsOrVersions;
842 SuggestsList += SuggestsOrList;
843 SuggestsVersions += SuggestsOrVersions;
844 }
845
846 }
847 }
848
849 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
850 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
851
852 }
853
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);
858
859 return InstallPackages(Cache,false);
860 }
861 /*}}}*/