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