]> git.saurik.com Git - apt.git/blob - apt-private/private-install.cc
reimplement build-dep via apts normal resolver
[apt.git] / apt-private / private-install.cc
1 // Include Files /*{{{*/
2 #include <config.h>
3
4 #include <apt-pkg/acquire.h>
5 #include <apt-pkg/acquire-item.h>
6 #include <apt-pkg/algorithms.h>
7 #include <apt-pkg/cachefile.h>
8 #include <apt-pkg/cacheset.h>
9 #include <apt-pkg/cmndline.h>
10 #include <apt-pkg/depcache.h>
11 #include <apt-pkg/error.h>
12 #include <apt-pkg/fileutl.h>
13 #include <apt-pkg/pkgrecords.h>
14 #include <apt-pkg/pkgsystem.h>
15 #include <apt-pkg/sptr.h>
16 #include <apt-pkg/strutl.h>
17 #include <apt-pkg/cacheiterators.h>
18 #include <apt-pkg/configuration.h>
19 #include <apt-pkg/macros.h>
20 #include <apt-pkg/packagemanager.h>
21 #include <apt-pkg/pkgcache.h>
22 #include <apt-pkg/upgrade.h>
23 #include <apt-pkg/install-progress.h>
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <algorithm>
28 #include <iostream>
29 #include <set>
30 #include <vector>
31 #include <map>
32
33 #include <apt-private/acqprogress.h>
34 #include <apt-private/private-install.h>
35 #include <apt-private/private-cachefile.h>
36 #include <apt-private/private-cacheset.h>
37 #include <apt-private/private-download.h>
38 #include <apt-private/private-output.h>
39
40 #include <apti18n.h>
41 /*}}}*/
42 class pkgSourceList;
43
44 bool CheckNothingBroken(CacheFile &Cache) /*{{{*/
45 {
46 // Now we check the state of the packages,
47 if (Cache->BrokenCount() == 0)
48 return true;
49
50 c1out <<
51 _("Some packages could not be installed. This may mean that you have\n"
52 "requested an impossible situation or if you are using the unstable\n"
53 "distribution that some required packages have not yet been created\n"
54 "or been moved out of Incoming.") << std::endl;
55 /*
56 if (Packages == 1)
57 {
58 c1out << std::endl;
59 c1out <<
60 _("Since you only requested a single operation it is extremely likely that\n"
61 "the package is simply not installable and a bug report against\n"
62 "that package should be filed.") << std::endl;
63 }
64 */
65
66 c1out << _("The following information may help to resolve the situation:") << std::endl;
67 c1out << std::endl;
68 ShowBroken(c1out,Cache,false);
69 if (_error->PendingError() == true)
70 return false;
71 else
72 return _error->Error(_("Broken packages"));
73 }
74 /*}}}*/
75 // InstallPackages - Actually download and install the packages /*{{{*/
76 // ---------------------------------------------------------------------
77 /* This displays the informative messages describing what is going to
78 happen and then calls the download routines */
79 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
80 {
81 if (_config->FindB("APT::Get::Purge",false) == true)
82 {
83 pkgCache::PkgIterator I = Cache->PkgBegin();
84 for (; I.end() == false; ++I)
85 {
86 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
87 Cache->MarkDelete(I,true);
88 }
89 }
90
91 bool Hold = false;
92 bool Downgrade = false;
93 bool Essential = false;
94
95 // Show all the various warning indicators
96 ShowDel(c1out,Cache);
97 ShowNew(c1out,Cache);
98 if (ShwKept == true)
99 ShowKept(c1out,Cache);
100 Hold = !ShowHold(c1out,Cache);
101 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
102 ShowUpgraded(c1out,Cache);
103 Downgrade = !ShowDowngraded(c1out,Cache);
104
105 if (_config->FindB("APT::Get::Download-Only",false) == false)
106 Essential = !ShowEssential(c1out,Cache);
107
108 // All kinds of failures
109 bool Fail = (Essential || Downgrade || Hold);
110
111 Stats(c1out,Cache);
112
113 // Sanity check
114 if (Cache->BrokenCount() != 0)
115 {
116 ShowBroken(c1out,Cache,false);
117 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
118 }
119
120 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
121 Cache->BadCount() == 0)
122 return true;
123
124 // No remove flag
125 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
126 return _error->Error(_("Packages need to be removed but remove is disabled."));
127
128 // Fail safe check
129 if (_config->FindI("quiet",0) >= 2 ||
130 _config->FindB("APT::Get::Assume-Yes",false) == true)
131 {
132 if (_config->FindB("APT::Get::Force-Yes",false) == true) {
133 _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead."));
134 }
135
136 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) {
137 if (Essential == true && _config->FindB("APT::Get::allow-remove-essential", false) == false)
138 return _error->Error(_("Essential packages were removed and -y was used without --allow-remove-essential."));
139 if (Downgrade == true && _config->FindB("APT::Get::allow-downgrades", false) == false)
140 return _error->Error(_("Packages were downgraded and -y was used without --allow-downgrades."));
141 if (Hold == true && _config->FindB("APT::Get::allow-change-held-packages", false) == false)
142 return _error->Error(_("Held packages were changed and -y was used without --allow-change-held-packages."));
143 }
144 }
145
146 // Run the simulator ..
147 if (_config->FindB("APT::Get::Simulate") == true)
148 {
149 pkgSimulate PM(Cache);
150
151 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
152 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
153 delete progress;
154
155 if (Res == pkgPackageManager::Failed)
156 return false;
157 if (Res != pkgPackageManager::Completed)
158 return _error->Error(_("Internal error, Ordering didn't finish"));
159 return true;
160 }
161
162 // Create the text record parser
163 pkgRecords Recs(Cache);
164 if (_error->PendingError() == true)
165 return false;
166
167 // Create the download object
168 aptAcquireWithTextStatus Fetcher;
169 if (_config->FindB("APT::Get::Print-URIs", false) == true)
170 {
171 // force a hashsum for compatibility reasons
172 _config->CndSet("Acquire::ForceHash", "md5sum");
173 }
174 else if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false)
175 return false;
176
177 // Read the source list
178 if (Cache.BuildSourceList() == false)
179 return false;
180 pkgSourceList *List = Cache.GetSourceList();
181
182 // Create the package manager and prepare to download
183 std::unique_ptr<pkgPackageManager> PM(_system->CreatePM(Cache));
184 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
185 _error->PendingError() == true)
186 return false;
187
188 // Display statistics
189 unsigned long long FetchBytes = Fetcher.FetchNeeded();
190 unsigned long long FetchPBytes = Fetcher.PartialPresent();
191 unsigned long long DebBytes = Fetcher.TotalNeeded();
192 if (DebBytes != Cache->DebSize())
193 {
194 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
195 c0out << _("How odd... The sizes didn't match, email apt@packages.debian.org") << std::endl;
196 }
197
198 // Number of bytes
199 if (DebBytes != FetchBytes)
200 //TRANSLATOR: The required space between number and unit is already included
201 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
202 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
203 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
204 else if (DebBytes != 0)
205 //TRANSLATOR: The required space between number and unit is already included
206 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
207 ioprintf(c1out,_("Need to get %sB of archives.\n"),
208 SizeToStr(DebBytes).c_str());
209
210 // Size delta
211 if (Cache->UsrSize() >= 0)
212 //TRANSLATOR: The required space between number and unit is already included
213 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
214 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
215 SizeToStr(Cache->UsrSize()).c_str());
216 else
217 //TRANSLATOR: The required space between number and unit is already included
218 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
219 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
220 SizeToStr(-1*Cache->UsrSize()).c_str());
221
222 if (_error->PendingError() == true)
223 return false;
224
225 if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false)
226 return false;
227
228 if (Essential == true && Safety == true && _config->FindB("APT::Get::allow-remove-essential", false) == false)
229 {
230 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
231 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
232
233 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
234 // careful with hard to type or special characters (like non-breaking spaces)
235 const char *Prompt = _("Yes, do as I say!");
236 ioprintf(c2out,
237 _("You are about to do something potentially harmful.\n"
238 "To continue type in the phrase '%s'\n"
239 " ?] "),Prompt);
240 c2out << std::flush;
241 if (AnalPrompt(Prompt) == false)
242 {
243 c2out << _("Abort.") << std::endl;
244 exit(1);
245 }
246 }
247 else
248 {
249 // Prompt to continue
250 if (Ask == true || Fail == true)
251 {
252 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
253 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
254
255 if (_config->FindI("quiet",0) < 2 &&
256 _config->FindB("APT::Get::Assume-Yes",false) == false)
257 {
258 c2out << _("Do you want to continue?") << std::flush;
259 if (YnPrompt() == false)
260 {
261 c2out << _("Abort.") << std::endl;
262 exit(1);
263 }
264 }
265 }
266 }
267
268 // Just print out the uris an exit if the --print-uris flag was used
269 if (_config->FindB("APT::Get::Print-URIs") == true)
270 {
271 pkgAcquire::UriIterator I = Fetcher.UriBegin();
272 for (; I != Fetcher.UriEnd(); ++I)
273 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
274 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
275 return true;
276 }
277
278 if (!CheckAuth(Fetcher, true))
279 return false;
280
281 /* Unlock the dpkg lock if we are not going to be doing an install
282 after. */
283 if (_config->FindB("APT::Get::Download-Only",false) == true)
284 _system->UnLock();
285
286 // Run it
287 while (1)
288 {
289 bool Transient = false;
290 if (_config->FindB("APT::Get::Download",true) == false)
291 {
292 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
293 {
294 if ((*I)->Local == true)
295 {
296 ++I;
297 continue;
298 }
299
300 // Close the item and check if it was found in cache
301 (*I)->Finished();
302 if ((*I)->Complete == false)
303 Transient = true;
304
305 // Clear it out of the fetch list
306 delete *I;
307 I = Fetcher.ItemsBegin();
308 }
309 }
310
311 bool Failed = false;
312 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
313 return false;
314
315 /* If we are in no download mode and missing files and there were
316 'failures' then the user must specify -m. Furthermore, there
317 is no such thing as a transient error in no-download mode! */
318 if (Transient == true &&
319 _config->FindB("APT::Get::Download",true) == false)
320 {
321 Transient = false;
322 Failed = true;
323 }
324
325 if (_config->FindB("APT::Get::Download-Only",false) == true)
326 {
327 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
328 return _error->Error(_("Some files failed to download"));
329 c1out << _("Download complete and in download only mode") << std::endl;
330 return true;
331 }
332
333 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
334 {
335 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
336 }
337
338 if (Transient == true && Failed == true)
339 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
340
341 // Try to deal with missing package files
342 if (Failed == true && PM->FixMissing() == false)
343 {
344 c2out << _("Unable to correct missing packages.") << std::endl;
345 return _error->Error(_("Aborting install."));
346 }
347
348 _system->UnLock();
349
350 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
351 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
352 delete progress;
353
354 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
355 return false;
356 if (Res == pkgPackageManager::Completed)
357 break;
358
359 // Reload the fetcher object and loop again for media swapping
360 Fetcher.Shutdown();
361 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
362 return false;
363
364 _system->Lock();
365 }
366
367 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
368 if (disappearedPkgs.empty() == false)
369 {
370 ShowList(c1out, P_("The following package disappeared from your system as\n"
371 "all files have been overwritten by other packages:",
372 "The following packages disappeared from your system as\n"
373 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappearedPkgs,
374 [](std::string const &Pkg) { return Pkg.empty() == false; },
375 [](std::string const &Pkg) { return Pkg; },
376 [](std::string const &) { return std::string(); });
377 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
378 }
379
380 // cleanup downloaded debs
381 if (_config->FindB("APT::Keep-Downloaded-Packages", true) == false)
382 {
383 std::string const archivedir = _config->FindDir("Dir::Cache::archives");
384 for (auto I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
385 {
386 if (flNotFile((*I)->DestFile) != archivedir || (*I)->Local)
387 continue;
388 RemoveFile("Keep-Downloaded-Packages=false", (*I)->DestFile);
389 }
390 }
391
392 return true;
393 }
394 /*}}}*/
395 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
396 // ---------------------------------------------------------------------
397 /* Remove unused automatic packages */
398 bool DoAutomaticRemove(CacheFile &Cache)
399 {
400 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
401 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
402 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
403
404 pkgDepCache::ActionGroup group(*Cache);
405 if(Debug)
406 std::cout << "DoAutomaticRemove()" << std::endl;
407
408 if (doAutoRemove == true &&
409 _config->FindB("APT::Get::Remove",true) == false)
410 {
411 c1out << _("We are not supposed to delete stuff, can't start "
412 "AutoRemover") << std::endl;
413 return false;
414 }
415
416 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
417 bool smallList = (hideAutoRemove == false &&
418 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
419
420 unsigned long autoRemoveCount = 0;
421 APT::PackageSet tooMuch;
422 SortedPackageUniverse Universe(Cache);
423 // look over the cache to see what can be removed
424 for (auto const &Pkg: Universe)
425 {
426 if (Cache[Pkg].Garbage)
427 {
428 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
429 if(Debug)
430 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
431
432 if (doAutoRemove)
433 {
434 if(Pkg.CurrentVer() != 0 &&
435 Pkg->CurrentState != pkgCache::State::ConfigFiles)
436 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
437 else
438 Cache->MarkKeep(Pkg, false, false);
439 }
440 else
441 {
442 // if the package is a new install and already garbage we don't need to
443 // install it in the first place, so nuke it instead of show it
444 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
445 {
446 if (Pkg.CandVersion() != 0)
447 tooMuch.insert(Pkg);
448 Cache->MarkDelete(Pkg, false, 0, false);
449 }
450 // only show stuff in the list that is not yet marked for removal
451 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
452 ++autoRemoveCount;
453 }
454 }
455 }
456
457 // we could have removed a new dependency of a garbage package,
458 // so check if a reverse depends is broken and if so install it again.
459 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
460 {
461 bool Changed;
462 do {
463 Changed = false;
464 for (APT::PackageSet::iterator Pkg = tooMuch.begin();
465 Pkg != tooMuch.end(); ++Pkg)
466 {
467 APT::PackageSet too;
468 too.insert(*Pkg);
469 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
470 Prv.end() == false; ++Prv)
471 too.insert(Prv.ParentPkg());
472 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
473 {
474 for (pkgCache::DepIterator R = P.RevDependsList();
475 R.end() == false; ++R)
476 {
477 if (R.IsNegative() == true ||
478 Cache->IsImportantDep(R) == false)
479 continue;
480 pkgCache::PkgIterator N = R.ParentPkg();
481 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
482 continue;
483 if (Debug == true)
484 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
485 Cache->MarkInstall(Pkg, false, 0, false);
486 if (hideAutoRemove == false)
487 ++autoRemoveCount;
488 tooMuch.erase(Pkg);
489 Changed = true;
490 break;
491 }
492 if (Changed == true)
493 break;
494 }
495 if (Changed == true)
496 break;
497 }
498 } while (Changed == true);
499 }
500
501 // Now see if we had destroyed anything (if we had done anything)
502 if (Cache->BrokenCount() != 0)
503 {
504 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
505 "shouldn't happen. Please file a bug report against apt.") << std::endl;
506 c1out << std::endl;
507 c1out << _("The following information may help to resolve the situation:") << std::endl;
508 c1out << std::endl;
509 ShowBroken(c1out,Cache,false);
510
511 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
512 }
513
514 // if we don't remove them, we should show them!
515 if (doAutoRemove == false && autoRemoveCount != 0)
516 {
517 if (smallList == false)
518 {
519 SortedPackageUniverse Universe(Cache);
520 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
521 "The following packages were automatically installed and are no longer required:",
522 autoRemoveCount), Universe,
523 [&Cache](pkgCache::PkgIterator const &Pkg) { return (*Cache)[Pkg].Garbage == true && (*Cache)[Pkg].Delete() == false; },
524 &PrettyFullName, CandidateVersion(&Cache));
525 }
526 else
527 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
528 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
529 std::string autocmd = "apt autoremove";
530 if (getenv("SUDO_USER") != NULL)
531 autocmd = "sudo " + autocmd;
532 ioprintf(c1out, P_("Use '%s' to remove it.", "Use '%s' to remove them.", autoRemoveCount), autocmd.c_str());
533 c1out << std::endl;
534 }
535 return true;
536 }
537 /*}}}*/
538 // DoCacheManipulationFromCommandLine /*{{{*/
539 static const unsigned short MOD_REMOVE = 1;
540 static const unsigned short MOD_INSTALL = 2;
541
542 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
543 {
544 std::vector<const char*> VolatileCmdL;
545 return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeMode);
546 }
547 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
548 {
549 std::map<unsigned short, APT::VersionSet> verset;
550 return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode);
551 }
552 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache,
553 std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
554 {
555 // Enter the special broken fixing mode if the user specified arguments
556 bool BrokenFix = false;
557 if (Cache->BrokenCount() != 0)
558 BrokenFix = true;
559
560 std::unique_ptr<pkgProblemResolver> Fix(nullptr);
561 if (_config->FindB("APT::Get::CallResolver", true) == true)
562 Fix.reset(new pkgProblemResolver(Cache));
563
564 unsigned short fallback = MOD_INSTALL;
565 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
566 fallback = MOD_REMOVE;
567 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
568 {
569 _config->Set("APT::Get::Purge", true);
570 fallback = MOD_REMOVE;
571 }
572 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0 ||
573 strcasecmp(CmdL.FileList[0], "auto-remove") == 0)
574 {
575 _config->Set("APT::Get::AutomaticRemove", "true");
576 fallback = MOD_REMOVE;
577 }
578
579 std::list<APT::VersionSet::Modifier> mods;
580 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
581 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::CANDIDATE));
582 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
583 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::NEWEST));
584 CacheSetHelperAPTGet helper(c0out);
585 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
586 CmdL.FileList + 1, mods, fallback, helper);
587
588 for (auto const &I: VolatileCmdL)
589 {
590 pkgCache::PkgIterator const P = Cache->FindPkg(I);
591 if (P.end())
592 continue;
593
594 // Set any version providing the .deb as the candidate.
595 for (auto Prv = P.ProvidesList(); Prv.end() == false; Prv++)
596 Cache.GetDepCache()->SetCandidateVersion(Prv.OwnerVer());
597
598 // via cacheset to have our usual virtual handling
599 APT::VersionContainerInterface::FromPackage(&(verset[MOD_INSTALL]), Cache, P, APT::CacheSetHelper::CANDIDATE, helper);
600 }
601
602 if (_error->PendingError() == true)
603 {
604 helper.showVirtualPackageErrors(Cache);
605 return false;
606 }
607
608
609 TryToInstall InstallAction(Cache, Fix.get(), BrokenFix);
610 TryToRemove RemoveAction(Cache, Fix.get());
611
612 // new scope for the ActionGroup
613 {
614 pkgDepCache::ActionGroup group(Cache);
615 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
616
617 for (unsigned short i = 0; order[i] != 0; ++i)
618 {
619 if (order[i] == MOD_INSTALL)
620 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
621 else if (order[i] == MOD_REMOVE)
622 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
623 }
624
625 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
626 {
627 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
628 InstallAction.doAutoInstall();
629 }
630
631 if (_error->PendingError() == true)
632 {
633 return false;
634 }
635
636 /* If we are in the Broken fixing mode we do not attempt to fix the
637 problems. This is if the user invoked install without -f and gave
638 packages */
639 if (BrokenFix == true && Cache->BrokenCount() != 0)
640 {
641 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
642 ShowBroken(c1out,Cache,false);
643 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
644 }
645
646 if (Fix != NULL)
647 {
648 // Call the scored problem resolver
649 OpTextProgress Progress(*_config);
650 bool const distUpgradeMode = strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0;
651
652 bool resolver_fail = false;
653 if (distUpgradeMode == true || UpgradeMode != APT::Upgrade::ALLOW_EVERYTHING)
654 resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode, &Progress);
655 else
656 resolver_fail = Fix->Resolve(true, &Progress);
657
658 if (resolver_fail == false && Cache->BrokenCount() == 0)
659 return false;
660 }
661
662 if (CheckNothingBroken(Cache) == false)
663 return false;
664 }
665 if (!DoAutomaticRemove(Cache))
666 return false;
667
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 }
679 /*}}}*/
680 // DoInstall - Install packages from the command line /*{{{*/
681 // ---------------------------------------------------------------------
682 /* Install named packages */
683 struct PkgIsExtraInstalled {
684 pkgCacheFile * const Cache;
685 APT::VersionSet const * const verset;
686 PkgIsExtraInstalled(pkgCacheFile * const Cache, APT::VersionSet const * const Container) : Cache(Cache), verset(Container) {}
687 bool operator() (pkgCache::PkgIterator const &Pkg)
688 {
689 if ((*Cache)[Pkg].Install() == false)
690 return false;
691 pkgCache::VerIterator const Cand = (*Cache)[Pkg].CandidateVerIter(*Cache);
692 return verset->find(Cand) == verset->end();
693 }
694 };
695 bool DoInstall(CommandLine &CmdL)
696 {
697 CacheFile Cache;
698 std::vector<char const *> VolatileCmdL;
699 Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
700
701 // then open the cache
702 if (Cache.OpenForInstall() == false ||
703 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
704 return false;
705
706 std::map<unsigned short, APT::VersionSet> verset;
707 if(!DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, 0))
708 return false;
709
710 /* Print out a list of packages that are going to be installed extra
711 to what the user asked */
712 SortedPackageUniverse Universe(Cache);
713 if (Cache->InstCount() != verset[MOD_INSTALL].size())
714 ShowList(c1out, _("The following additional packages will be installed:"), Universe,
715 PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]),
716 &PrettyFullName, CandidateVersion(&Cache));
717
718 /* Print out a list of suggested and recommended packages */
719 {
720 std::list<std::string> Recommends, Suggests, SingleRecommends, SingleSuggests;
721 for (auto const &Pkg: Universe)
722 {
723 /* Just look at the ones we want to install */
724 if ((*Cache)[Pkg].Install() == false)
725 continue;
726
727 // get the recommends/suggests for the candidate ver
728 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
729 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
730 {
731 pkgCache::DepIterator Start;
732 pkgCache::DepIterator End;
733 D.GlobOr(Start,End); // advances D
734 if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests)
735 continue;
736
737 {
738 // Skip if we already saw this
739 std::string target;
740 for (pkgCache::DepIterator I = Start; I != D; ++I)
741 {
742 if (target.empty() == false)
743 target.append(" | ");
744 target.append(I.TargetPkg().FullName(true));
745 }
746 std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? SingleRecommends : SingleSuggests;
747 if (std::find(Type.begin(), Type.end(), target) != Type.end())
748 continue;
749 Type.push_back(target);
750 }
751
752 std::list<std::string> OrList;
753 bool foundInstalledInOrGroup = false;
754 for (pkgCache::DepIterator I = Start; I != D; ++I)
755 {
756 {
757 // satisfying package is installed and not marked for deletion
758 APT::VersionList installed = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::INSTALLED);
759 if (std::find_if(installed.begin(), installed.end(),
760 [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Delete() == false; }) != installed.end())
761 {
762 foundInstalledInOrGroup = true;
763 break;
764 }
765 }
766
767 {
768 // satisfying package is upgraded to/new install
769 APT::VersionList upgrades = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::CANDIDATE);
770 if (std::find_if(upgrades.begin(), upgrades.end(),
771 [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Upgrade(); }) != upgrades.end())
772 {
773 foundInstalledInOrGroup = true;
774 break;
775 }
776 }
777
778 if (OrList.empty())
779 OrList.push_back(I.TargetPkg().FullName(true));
780 else
781 OrList.push_back("| " + I.TargetPkg().FullName(true));
782 }
783
784 if(foundInstalledInOrGroup == false)
785 {
786 std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests;
787 std::move(OrList.begin(), OrList.end(), std::back_inserter(Type));
788 }
789 }
790 }
791 auto always_true = [](std::string const&) { return true; };
792 auto string_ident = [](std::string const&str) { return str; };
793 auto verbose_show_candidate =
794 [&Cache](std::string str)
795 {
796 if (APT::String::Startswith(str, "| "))
797 str.erase(0, 2);
798 pkgCache::PkgIterator const Pkg = Cache->FindPkg(str);
799 if (Pkg.end() == true)
800 return "";
801 return (*Cache)[Pkg].CandVersion;
802 };
803 ShowList(c1out,_("Suggested packages:"), Suggests,
804 always_true, string_ident, verbose_show_candidate);
805 ShowList(c1out,_("Recommended packages:"), Recommends,
806 always_true, string_ident, verbose_show_candidate);
807 }
808
809 // See if we need to prompt
810 // FIXME: check if really the packages in the set are going to be installed
811 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
812 return InstallPackages(Cache,false,false);
813
814 return InstallPackages(Cache,false);
815 }
816 /*}}}*/
817
818 // TryToInstall - Mark a package for installation /*{{{*/
819 void TryToInstall::operator() (pkgCache::VerIterator const &Ver) {
820 if (unlikely(Ver.end()))
821 {
822 _error->Fatal("The given version to TryToInstall is invalid!");
823 return;
824 }
825 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
826 if (unlikely(Pkg.end()))
827 {
828 _error->Fatal("The given version to TryToInstall has an invalid parent package!");
829 return;
830 }
831
832 Cache->GetDepCache()->SetCandidateVersion(Ver);
833 pkgDepCache::StateCache &State = (*Cache)[Pkg];
834
835 // Handle the no-upgrade case
836 if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
837 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
838 Pkg.FullName(true).c_str());
839 // Ignore request for install if package would be new
840 else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
841 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
842 Pkg.FullName(true).c_str());
843 else {
844 if (Fix != NULL) {
845 Fix->Clear(Pkg);
846 Fix->Protect(Pkg);
847 }
848 Cache->GetDepCache()->MarkInstall(Pkg,false);
849
850 if (State.Install() == false) {
851 if (_config->FindB("APT::Get::ReInstall",false) == true) {
852 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
853 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
854 Pkg.FullName(true).c_str());
855 else
856 Cache->GetDepCache()->SetReInstall(Pkg, true);
857 } else
858 // TRANSLATORS: First string is package name, second is version
859 ioprintf(c1out,_("%s is already the newest version (%s).\n"),
860 Pkg.FullName(true).c_str(), Pkg.CurrentVer().VerStr());
861 }
862
863 // Install it with autoinstalling enabled (if we not respect the minial
864 // required deps or the policy)
865 if (FixBroken == false)
866 doAutoInstallLater.insert(Pkg);
867 }
868
869 // see if we need to fix the auto-mark flag
870 // e.g. apt-get install foo
871 // where foo is marked automatic
872 if (State.Install() == false &&
873 (State.Flags & pkgCache::Flag::Auto) &&
874 _config->FindB("APT::Get::ReInstall",false) == false &&
875 _config->FindB("APT::Get::Only-Upgrade",false) == false &&
876 _config->FindB("APT::Get::Download-Only",false) == false)
877 {
878 ioprintf(c1out,_("%s set to manually installed.\n"),
879 Pkg.FullName(true).c_str());
880 Cache->GetDepCache()->MarkAuto(Pkg,false);
881 AutoMarkChanged++;
882 }
883 }
884 /*}}}*/
885 bool TryToInstall::propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > const &start, std::ostream &out)/*{{{*/
886 {
887 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
888 s != start.end(); ++s)
889 Cache->GetDepCache()->SetCandidateVersion(s->first);
890
891 bool Success = true;
892 // the Changed list contains:
893 // first: "new version"
894 // second: "what-caused the change"
895 std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
896 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
897 s != start.end(); ++s)
898 {
899 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
900 // We continue here even if it failed to enhance the ShowBroken output
901 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
902 }
903 for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
904 c != Changed.end(); ++c)
905 {
906 if (c->second.end() == true)
907 ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
908 c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
909 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
910 {
911 pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
912 ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
913 V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
914 }
915 }
916 return Success;
917 }
918 /*}}}*/
919 void TryToInstall::doAutoInstall() { /*{{{*/
920 for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
921 P != doAutoInstallLater.end(); ++P) {
922 pkgDepCache::StateCache &State = (*Cache)[P];
923 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
924 continue;
925 Cache->GetDepCache()->MarkInstall(P, true);
926 }
927 doAutoInstallLater.clear();
928 }
929 /*}}}*/
930 // TryToRemove - Mark a package for removal /*{{{*/
931 void TryToRemove::operator() (pkgCache::VerIterator const &Ver)
932 {
933 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
934
935 if (Fix != NULL)
936 {
937 Fix->Clear(Pkg);
938 Fix->Protect(Pkg);
939 Fix->Remove(Pkg);
940 }
941
942 if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
943 (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
944 {
945 pkgCache::GrpIterator Grp = Pkg.Group();
946 pkgCache::PkgIterator P = Grp.PackageList();
947 for (; P.end() != true; P = Grp.NextPkg(P))
948 {
949 if (P == Pkg)
950 continue;
951 if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
952 {
953 // TRANSLATORS: Note, this is not an interactive question
954 ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
955 Pkg.FullName(true).c_str(), P.FullName(true).c_str());
956 break;
957 }
958 }
959 if (P.end() == true)
960 ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
961
962 // MarkInstall refuses to install packages on hold
963 Pkg->SelectedState = pkgCache::State::Hold;
964 }
965 else
966 Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
967 }
968 /*}}}*/